是设计模式,我们有救了!!!(二、工厂模式)

github.com/YaYiXiBa/Ja... 欢迎去看我的代码哦。。。


highlight: a11y-dark

1. 简单工厂模式 (Simple Factory)

优点:

  • ​实现简单​:结构简单,易于理解和实现

缺点:

  • ​违反开闭原则​:增加新产品需要修改工厂类逻辑
  • ​职责过重​:工厂类集中了所有产品的创建逻辑
  • ​扩展性差​:当产品类型较多时,工厂方法会变得臃肿 首先,先尝试实现以下类图:
typescript 复制代码
//工厂类
public class SimpleFactory {
    public static Shape getShape(String shapeType) {
        if (shapeType.equalsIgnoreCase("Square")) {
            return new Square();
        }else if (shapeType.equalsIgnoreCase("Circle")) {
            return new Circle();
        }else if (shapeType.equalsIgnoreCase("Triangle")) {
            return new Trangle();
        }else{
            return null;
        }
    }
}
//客户端
public class Client {
    public static void main(String[] args) {
        Shape square = SimpleFactory.getShape("Square");
        assert square != null;
        square.draw();
    }
}
//运行结果
Drawing Square

Process finished with exit code 0

简单工厂模式存在,却又经常被说是不算严格的设计模式。为什么呢? 看一下类图:我们就是将手动new对象的方法进行了封装,把他们都放在了一个类中,作为静态方法getShape(String shapeType) 来调用。所以说,他简单。同时也带来了前文所述的缺点。

2. 工厂方法模式 (Factory Method)

先看图,其实可以去自己尝试实现一下。

这是一个使用手机工厂和电脑工厂实现生产产品的例子。很形象,但是建议注意细节:

  1. Product是所有产品类都要实现的接口,里面有一个展示功能的方法showFunction()。如此一来,任何工厂产出的物品就得到了统一,不管是生产手机,还是生产电脑,都可以返回Product。
  2. 手机工厂里的生产步骤是new Phone(),电脑工厂是new PC()。Phone和PC都实现了Product接口,都可以作为Product返回。
  3. 既然所有工厂都是在生产Product,不妨就把createProduct方法抽象出来,放在Factory接口中,要求所有的实际工厂都要实现这个接口。

先贴出部分代码,后续会给出github链接:

java 复制代码
public interface Product {
    public void showFunction();
}

public interface Factory {
    public Product createProduct();
}


public class PCFactory implements Factory{
    @Override
    public Product createProduct() {
        return new PersonalComputer();
    }
}


public class Phone implements Product{
    @Override
    public void showFunction() {
        System.out.println("手机可以打电话");
    }
}

public class Client {
    public static void main(String[] args) {
        Factory pcFactory = new PCFactory();
        Product pc = pcFactory.createProduct();
        pc.showFunction();

        PhoneFactory phoneFactory = new PhoneFactory();
        Product phone = phoneFactory.createProduct();
        phone.showFunction();
    }
}

优点:

  • ​符合开闭原则​:增加新产品只需添加新的工厂子类,无需修改现有代码
  • ​单一职责原则​:每个具体工厂只负责创建一种产品
  • ​灵活性高​:可以形成基于继承的等级结构
  • ​解耦彻底​:客户端只需要知道抽象工厂和抽象产品

缺点:

  • ​类数量增加​:每增加一个产品就需要增加一个具体工厂类
  • ​复杂性增加​:引入了抽象层,增加了系统的抽象性和理解难度
  • ​需要额外开销​:需要编写更多的类和接口

3. 抽象工厂模式 (Abstract Factory)

如果你彻底理解了工厂模式,那么抽象工厂很容易理解了。重点在于"抽象"二字。先看一下类图(哎,自己电脑装的是社区版生成不了diagram凑合看下吧。。。)

给出几个factory的代码,带着问题看:

  1. 创建产品的方式:public Color getColor(String colorName)、public Product getProduct(String productName)。Color和Product都是产品。这不是又回到了简单工厂的方式吗?在方法工厂中我们是使用单独的工厂来创建单独的产品。但抽象工厂面向的场景是,生产一组具有相互依赖关系的产品。比如各种"颜色"和各种电子产品。"红色"的"手机"和"黑色"的"手表",我们将其视为两组产品,他们之间是具有绑定关系的产品。试想,现在我现在就要生产"红色"的"手机"和"黑色"的"手表"。如果按照工厂方法的方式,在客户端,是不是要new四个工厂,分别生产四种对象。所以在这种场景下,如果将"电子设备"和"颜色"独立开,让ColorFactory和ProductFactory分别负责一类产品的生产,在客户端的操作就更方便一些。
  2. 关于"抽象":现在两个工厂的职责已经分开了,但是在客户端(也就是图中的AbstractFactoryParttenDemo,代码里我直接写的Client)与实际工厂之间仍然加了一层抽象,也就是抽象工厂。这里的目的在于让客户端代码只依赖抽象接口,让"解耦"更加彻底。这样即使工厂在创建产品的过程中发生了步骤上的变化,客户端的代码也不需要改动,因为引入的只是工厂实现类的上层抽象。注意看客户端的两行代码:

Factory colorFactory = FactoryProducer.getFactory("ColorFactory");

Factory productFactory = FactoryProducer.getFactory("ProductFactory");在客户端看来,管你是什么工厂实现类,我都按照Factory类来接受,然后给你一个局部变量则我这边做个标识就可以了。这样哪怕你有一天不叫ColorFactory了,改成"ColorMakeFactory"或者换了别的工厂来生产某个产品都无所谓。

3.为什么还有FactoryProducer:这里的逻辑其实就是在根据名称返回具体的实现类对吧? "名称"是客户端传来的,那么new出实际的工厂应该是谁来负责呢?肯定不能交给客户端吧。当然是属于我们提供给客户端的入口。客户端只需要调用FactoryProducer的getFactory方法就可以到到想要的工厂,这就叫做"无需关心具体的实现"。

csharp 复制代码
public abstract class  Factory {
    public abstract Product getProduct(String productName);
    public abstract Color getColor(String colorName);
}
scala 复制代码
public class ColorFactory extends Factory{
    @Override
    public Product getProduct(String productName) {

        return null;
    }

    @Override
    public Color getColor(String colorName) {
        if(Objects.equals(colorName, "red")){
            return new Red();
        }else if(colorName.equals("black")){
            return new Black();
        }else if (colorName.equals("yellow")){
            return new Yellow();
        }
        return null;
    }
}
scala 复制代码
public class ProductFactory extends Factory{
    @Override
    public Product getProduct(String productName) {
        if(productName.equals("PC")){
            return new PC();
        }else if(productName.equals("Phone")){
            return new Phone();
        }else if(productName.equals("Watch")){
            return new Watch();
        }
        return null;
    }

    @Override
    public Color getColor(String colorName) {
        return null;
    }
}
csharp 复制代码
public class FactoryProducer {
    public static Factory getFactory(String factoryName){
        if(factoryName.equals("ColorFactory")){
            return new ColorFactory();
        } else if (factoryName.equals("ProductFactory")) {
            return new ProductFactory();
        }else{
            throw new RuntimeException("名称有误");
        }
    }
}
ini 复制代码
public class Client {
    public static void main(String[] args) {
        Factory colorFactory = FactoryProducer.getFactory("ColorFactory");
        Factory productFactory = FactoryProducer.getFactory("ProductFactory");
        Color red = colorFactory.getColor("red");
        Product watch = productFactory.getProduct("Watch");
        red.showColor();
        watch.showFunction();

        Color yellow = colorFactory.getColor("yellow");
        Product phone = productFactory.getProduct("Phone");
        yellow.showColor();
        phone.showFunction();
    }
}
运行结果:
红色
手表可以装*
黄色
手机可以打电话

Process finished with exit code 0

优点:

  • ​产品族支持​:能创建一组相关或依赖的对象
  • ​一致性保证​:保证客户端始终只使用同一个产品族中的对象
  • ​开闭原则​:易于扩展产品族,增加新的产品族很方便
  • ​解耦彻底​:客户端与具体类实现分离

缺点:

  • ​扩展产品等级困难​:增加新产品需要修改抽象工厂接口及所有具体工厂类
  • ​类数量激增​:支持的产品族和产品等级越多,系统越复杂
  • ​设计复杂​:需要精心设计接口,否则难以应对变化

对比总结

模式 创建对象方式 扩展新产品 扩展新产品族 适用场景
简单工厂 集中创建 修改工厂类 不支持 对象较少,变化不大
工厂方法 子类创建 添加子类 不支持 单一产品,需要灵活扩展
抽象工厂 产品族创建 修改接口 添加子类 相关产品族,强调一致性

​选择建议​​:

  • 当产品类型较少且不经常变化时,使用简单工厂
  • 当需要灵活创建单一产品时,使用工厂方法
  • 当需要创建一组相关产品时,使用抽象工厂 github.com/YaYiXiBa/Ja... 欢迎去看我的代码哦。。。
相关推荐
Livingbody41 分钟前
ubuntu25.04完美安装typora免费版教程
后端
阿华的代码王国1 小时前
【Android】RecyclerView实现新闻列表布局(1)适配器使用相关问题
android·xml·java·前端·后端
码农BookSea1 小时前
自研 DSL 神器:万字拆解 ANTLR 4 核心原理与高级应用
java·后端
lovebugs1 小时前
Java并发编程:深入理解volatile与指令重排
java·后端·面试
海奥华21 小时前
操作系统到 Go 运行时的内存管理演进与实现
开发语言·后端·golang
codervibe1 小时前
Spring Boot 服务层泛型抽象与代码复用实战
后端
_風箏1 小时前
Shell【脚本 04】传递参数的4种方式(位置参数、特殊变量、环境变量和命名参数)实例说明
后端
斜月1 小时前
Python Asyncio以及Futures并发编程实践
后端·python
CRUD被占用了1 小时前
coze-studio学习笔记(一)
后端