通俗易懂的java设计模式之工厂模式

它的职责是将对象从new的泥潭里解救出来,隐藏对象的构造细节,实现了对象构造和具体实现的解耦。同时它又区别于Spring Ioc的控制反转,Ioc通过反射技术实现,而工厂模式只是封装了构造细节,实现还是传统的构造方法来实现,所以Ioc更加灵活。你可能就有疑问了,既然Ioc这么灵活我还考虑工厂模式干嘛,实际上工厂模式也有它的好处,详见如下表格。

我们一定要根据实际场景灵活选用,学习技术不是为了炫耀什么,而只是用合适的技术解决当下的业务仅此而已,哪怕所用技术很简单。说白了,不能为了用而用!

接下来介绍下工厂模式的几种类型:

一、简单工厂模式

我们应该明确的知道,既然是一个工厂,那么必然这个工厂不止可以生成一个产品,它应该可以根据实际需要,创造出更多的同类产品(工厂的职责要单一,这样符合单一职责的设计原则)。既然产品可以是多个,那么我们应该明确告知工厂,我们要的是哪一种产品,很显然通过一个type类型即可实现,我以一个咖啡工厂举例,代码如下:

scala 复制代码
scala复制代码public class SimpleFactoryMethod {
    public static void main(String[] args) {
        Coffee coffee = SimpleCoffeeFactory.createCoffee(2);
        coffee.drink();
    }
}
class SimpleCoffeeFactory{
    public static Coffee createCoffee(int type){
        if(type == 1){
            return new CoffeeA();
        }else {
            return new CoffeeB();
        }
    }
}
abstract class Coffee{
    public abstract void drink();
}
class CoffeeA extends Coffee{
    @Override
    public void drink() {
        System.out.println("drink A");
    }
}
class CoffeeB extends Coffee{
    @Override
    public void drink() {
        System.out.println("drink B");
    }
}

这样我们就能根据type类型是1还是2,决定工厂生产的产品是A咖啡还是B咖啡,当然这里只是举例,type类型最好使用枚举进行实现。

二、工厂方法模式

在简单工厂模式下,我们通过类型来告诉工厂我们要生产的具体产品是哪个,那还有其他的方式吗,这个时候就要用到了我们常见的接口。这样就衍生了几个概念,抽象工厂,具体工厂和具体产品。代码如下:

typescript 复制代码
typescript复制代码public class NormalFactoryMethod {
    public static void main(String[] args) {
        CoffeeFactory coffeeFactory = new AmericanCoffeeFactory();
        Coffee coffee = coffeeFactory.createCoffee();
        coffee.drink();
    }
}
// 抽象工厂
interface CoffeeFactory {
    Coffee createCoffee();
}
// 具体工厂
class LatteCoffeeFactory implements CoffeeFactory {
    // 具体产品:咖啡A
    public Coffee createCoffee() {
        return new CoffeeA();
    }
}
class AmericanCoffeeFactory implements CoffeeFactory {
    // 具体产品:咖啡B
    public Coffee createCoffee() {
        return new CoffeeB();
    }
}

这样我们在写业务代码时,仅需要决定创建A工厂还是B工厂,就能决定最终我们需要的是哪一种产品。

细心的你发现了,既然工厂都可以有个抽象工厂,那产品不能有一个抽象产品吗,答案是当然可以啦,这就是我接下来要说的抽象工厂模式。

三、抽象工厂模式

该模式中工厂有抽象工厂和具体工厂,产品有抽象产品和具体产品,它强调的是一个产品族。

例如现有一个海尔工厂,生产的产品有冰箱和电视,后来又有了一个Tcl工厂,也是生产冰箱和电视,那么它们共性的地方就是它们都生产冰箱和电视。

代码如下:

scala 复制代码
scala复制代码public class AbstractFactoryMethod {
    public static void main(String[] args) {
        CoreFactory coreFactory = new HaierFactory();
        TvCore tvCore = coreFactory.CreateTvCore();
        tvCore.show();
    }
}
// 抽象工厂
abstract class CoreFactory{
    abstract TvCore CreateTvCore();
    abstract BxCore CreateBxCore();
}
// 具体工厂(海尔工厂)
class HaierFactory extends CoreFactory{
    @Override
    TvCore CreateTvCore() {
        return new HaierTvCore();
    }
    @Override
    BxCore CreateBxCore() {
        return new HaierBxCore();
    }
}
// 具体工厂(Tcl工厂)
class TclFactory extends CoreFactory{
    @Override
    TvCore CreateTvCore() {
        return new TclTvCore();
    }
    @Override
    BxCore CreateBxCore() {
        return new TclBxCore();
    }
}
// 抽象产品(电视)
abstract class TvCore{
    public abstract void show();
}
// 具体产品(海尔电视)
class HaierTvCore extends TvCore{
    @Override
    public void show() {
        System.out.println("海尔电视");
    }
}
// 具体产品(Tcl电视)
class TclTvCore extends TvCore{
    @Override
    public void show() {
        System.out.println("Tcl电视");
    }
}
// 抽象产品(冰箱)
abstract class BxCore{
    public abstract void show();
}
// 具体产品(海尔冰箱)
class HaierBxCore extends BxCore{
    @Override
    public void show() {
        System.out.println("海尔冰箱");
    }
}
// 具体产品(Tcl冰箱)
class TclBxCore extends BxCore{
    @Override
    public void show() {
        System.out.println("Tcl冰箱");
    }
}

最终运行效果:

复制代码
海尔电视

由此可见,找到每个工厂生产的产品存在共性的地方,这个尤为重要!

结束。

相关推荐
苍何9 小时前
WorkBuddy + 飞书的 8 种神仙用法(建议收藏)
后端
Captaincc9 小时前
掘金AI用量统计v0.1.0大更新-支持桌面宠物自定义和订阅额度卡片
前端·后端
大哥430910 小时前
AI 接口高并发 ≠ 秒杀高并发:为什么我把并发闸门挂在 LLM 调用汇聚点
后端
大哥430910 小时前
Redis 主从下的库存一致性:我推翻了"付款前查库存"这个方案
后端
ikoala10 小时前
DeepSeek 官方仓库惊现 DeepSeek Harness 桌面端!
前端·javascript·后端
用户4085274441410 小时前
一个个人开发者,怎么啃下 12 种工控协议?
后端
Bs_MoneyMagnet11 小时前
基于springboot+vue的旅游景区点评系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·旅游
cpp_learner11 小时前
Qt 5.14.2 x86_64 静态编译 —— 从零搭建完整手册
后端
企业数字化笔记12 小时前
固定资产历史数据怎么导入系统?Excel模板、字段映射和数据校验
android·java·数据库·后端
西瓜太郎123412 小时前
request_id 如何串起请求、路由、计费和日志
后端·python