文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JAVA设计模式之工厂模式(三种工厂模式)

2023-09-04 20:51

关注

1.工厂模式可以分为三类:

简单工厂其实不是一个标准的的设计模式。GOF 23 种设计模式中只有「工厂方法模式」与「抽象工厂模式」。简单工厂模式可以看为工厂方法模式的一种特例,为了统一整理学习,就都归为工厂模式。

这三种工厂模式在设计模式的分类中都属于创建型模式,三种模式从上到下逐步抽象。

2.创建型模式

创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。

创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。

创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。

工厂模式是创建型模式中比较重要的。工厂模式的主要功能就是帮助我们实例化对象。之所以名字中包含工厂模式四个字,是因为对象的实例化过程是通过工厂实现的,是用工厂代替 new 操作的。

3.工厂模式优点:

4.适用场景

不管是简单工厂模式,工厂方法模式还是抽象工厂模式,他们具有类似的特性,所以他们的适用场景也是类似的。

首先,作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

其次,工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。将会大大降低对象之间的耦合度。

再次,由于工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。也就是说,当需要系统有比较好的扩展性时,可以考虑工厂模式,不同的产品用不同的实现工厂来组装。

一、简单工厂模式

1、简单工厂模式的角色

简单工厂模式的角色如下:

角色解释
简单工厂SimpleFactory负责创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
抽象产品IProduct简单工厂创建的多有对象的父类,负责描述所有实例共有的公共接口。
具体产品ConcreteProduct简单共产模式的创建目标

2、UML 类图

3、简单工厂模式的通用写法

抽象产品类IProduct:

public interface IProuduct {    void doSomeThing();}

具体产品类ProductA:

@Slf4jpublic class ProductA implements IProuduct {    @Override    public void doSomeThing() {        log.info("我是ProductA");    }}

具体产品类ProductB:

@Slf4jpublic class ProductB implements IProuduct {    @Override    public void doSomeThing() {        log.info("我是ProductB");    }}

简单工厂类SimpleFactory(通过传入的productName来决定生成哪个具体产品)

public class SimpleFactory {    static IProuduct makeProduct(String productName) {        if ("ProductA".equals(productName)) {            return new ProductA();        } else if ("ProductB".equals(productName)) {            return new ProductB();        } else {            return null;        }    }}

客户端Client类:

public class Client {    public static void main(String[] args) {        // 生成产品B        IProuduct product = SimpleFactory.makeProduct("ProductB");        product.doSomeThing();    }}

在简单工厂模式中,抽象产品既可以是各个具体产品类实现的共同的接口,也可以是各个具体产品类继承的抽象父类。

4、 简单工厂模式总结

优点

简单工厂模式,封装了创建对象的逻辑,完成了创建对象逻辑与业务代码逻辑的解耦。试想客户端是多个service层的文件,对比不使用简单工厂模式,当我们要改变产生对象的逻辑时,需要在多个service文件中找到这部分代码进行修改。在使用简单工厂模式后,只需要修改简单工厂中生成对象的逻辑即可,不需要修改业务代码。完成了解耦。

缺点:

每当具体产品类的抽象产品类增多时,会需要在简单工厂类中新增关于新增产品类对象生成的方法。当抽象产品类很多时,抽象工厂会很臃肿。并且在这种情形下,SimpleFactory类也不符合开闭原则。

二、工厂方法模式

工厂方法模式:定义创建对象的接口,但具体实现放到实现这个接口的管理具体一类产品的对象生成的工厂类中去实现。

1、工厂方法模式的角色

角色解释
抽象工厂定义了创建抽象产品的方法,任何在模式中创建对象的工厂类都必须实现这个接口
具体工厂实现抽象工厂接口的具体工厂类,负责生产具体的产品
抽象产品工厂方法模式所创建的对象的超类型。也是产品对象的共同父类或者共同拥有的接口
具体产品实现了抽象产品角色所定义的接口。某具体产品由具体工厂创建,他们往往一一对应

2、UML 类图

3、工厂方法模式的通用写法

抽象工厂:

public interface IFactory {    IProduct makeProduct();}

抽象产品:

public interface IProduct {    void doSomeThing();}

具体产品ProductA:

@Slf4jpublic class ProductA implements IProduct {    @Override    public void doSomeThing() {        log.info("我是productA");    }}

具体产品ProductB:

@Slf4jpublic class ProductB implements IProduct {    @Override    public void doSomeThing() {        log.info("我是ProductB");    }}

生产ProductA的具体工厂FactoryA:

public class FactoryA implements IFactory {    @Override    public IProduct makeProduct() {        return new ProductA();    }}

生产ProductB的具体工厂FactoryB:

public class FactoryB implements IFactory {    @Override    public IProduct makeProduct() {        return new ProductB();    }}

客户端:

public class Client {    public static void main(String[] arges) {        // 生产ProductA        FactoryA factoryA = new FactoryA();        factoryA.makeProduct().doSomeThing();    }}

4、工厂方法模式适用场景

工厂方法模式和简单工厂模式虽然都是通过工厂来创建对象,他们之间最大的不同是——工厂方法模式在设计上完全完全符合“开闭原则”。

在以下情况下可以使用工厂方法模式:

使用场景:

5、工厂方法模式总结

从简单工厂模式的讲述知道:简单工厂的一个缺点在于,每当需要新增产品时,都需要修改负责生产产品的SimpleFactory类,违背了“开闭原则”,并且会使SimpleFactory类十分的臃肿。而使用工厂方法模式后,当新增ProductC时,只需要对应创建具体产品类ProductC和负责生产ProductC的具体工厂FactoryC即可。符合“开闭原则”,便于扩展。

它的缺点在于:

(1)类的个数容易过多,增加复杂度

(2)实现抽象工厂接口的具体工厂只能生产出一种产品(可以用抽象工厂模式解决)

三、抽象工厂模式

抽象工厂模式在工厂方法模式的基础上进行进一步抽象。设想下面这种场景:

现有两种具体产品(具体产品):篮球,足球(在此基础上的抽象产品可看成球)。同时,对于足球和篮球来说,他们都有两种品牌安踏、李宁。

如果采用工厂方法模式解决上述场景中创建产品的问题,需要在抽象工厂中定义创建产品的方法,并新建四个用于创建具体产品的具体工厂类:用于创建“李宁篮球”的具体工厂,用于创建“李宁足球”的具体工厂,用于创建“安踏篮球”的具体工厂,用于创建“安踏足球”的具体工厂。

从上面的解决方式可以看出:使用工厂方法模式,创建了很多具体工厂类,而没有利用产品的“商品族”的概念。

由此引出,抽象工厂模式是用于解决“一类产品”的创建问题(在上述场景中,可以把“李宁篮球”,“李宁足球”,“安踏篮球”,“安踏足球”归纳为:“篮球”,“足球”这两类商品)

1、抽象工厂模式的角色

角色解释
抽象工厂声明创建抽象产品对象的一个接口(有几个产品组,则声明几个方法。比如对于上述的场景,需要声明一个用于生产篮球类产品的方法,还需要声明一个用于生产足球类产品的方法)
具体工厂实现创建具体产品对象的操作
抽象产品为一类产品对象的抽象
具体产品定义一个将被相应的具体工厂创建的产品对象(比如上述场景中的:李宁篮球)

2、UML 类图

3、抽象工厂模式的通用写法

抽象工厂:

public interface AbstractFactory {    Basketball makeBasketball();    Football makeFootball();}

抽象产品族篮球:

public interface Basketball {    void sayBasketball();}

抽象产品族足球:

public interface Football {    void sayFootball();}

四个具体产品:李宁篮球、李宁足球、安踏篮球、安踏足球

@Slf4jpublic class LiningBasketball implements Basketball {    @Override    public void sayBasketball() {        log.info("我是李宁篮球");    }}@Slf4jpublic class LiningFootball implements Football {    @Override    public void sayFootball() {        log.info("我是李宁足球");    }}@Slf4jpublic class AntaBasketball implements Basketball {    @Override    public void sayBasketball() {        log.info("我是安踏篮球");    }}@Slf4jpublic class AntaFootball implements Football {    @Override    public void sayFootball() {        log.info("我是安踏足球");    }}

具体工厂:

public class LiningFactoy implements AbstractFactory {    @Override    public Basketball makeBasketball() {        return new LiningBasketball();    }    @Override    public Football makeFootball() {        return new LiningFootball();    }}public class AntaFactory implements AbstractFactory {    @Override    public Basketball makeBasketball() {        return new AntaBasketball();    }    @Override    public Football makeFootball() {        return new AntaFootball();    }}

客户端:

public class Client {    public static void main(String[] args){        // 生产李宁篮球和安踏足球        LiningFactoy liningFactoy = new LiningFactoy();        AntaFactory antaFactory = new AntaFactory();        liningFactoy.makeBasketball().sayBasketball();        antaFactory.makeFootball().sayFootball();    }}

4、抽象工厂模式适用场景

抽象工厂模式和工厂方法模式一样,都符合开闭原则。但是不同的是,工厂方法模式在增加一个具体产品的时候,都要增加对应的工厂。但是抽象工厂模式只有在新增一个类型的具体产品时才需要新增工厂。也就是说,工厂方法模式的一个工厂只能创建一个具体产品。而抽象工厂模式的一个工厂可以创建属于一类类型的多种具体产品。工厂创建产品的个数介于简单工厂模式和工厂方法模式之间。

在以下情况下可以使用抽象工厂模式:

“开闭原则”的倾斜性

在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦,抽象工厂模式的这种性质称为**“开闭原则”的倾斜性**。“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的,对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:

正因为抽象工厂模式存在“开闭原则”的倾斜性,它以一种倾斜的方式来满足“开闭原则”,为增加新产品族提供方便,但不能为增加新产品结构提供这样的方便,因此要求设计人员在设计之初就能够全面考虑,不会在设计完成之后向系统中增加新的产品等级结构,也不会删除已有的产品等级结构,否则将会导致系统出现较大的修改,为后续维护工作带来诸多麻烦。

5、抽象工厂模式总结

抽象工厂模式是工厂方法模式的进一步延伸,由于它提供了功能更为强大的工厂类并且具备较好的可扩展性,在软件开发中得以广泛应用,尤其是在一些框架和 API 类库的设计中,例如在 Java 语言的 AWT(抽象窗口工具包)中就使用了抽象工厂模式,它使用抽象工厂模式来实现在不同的操作系统中应用程序呈现与所在操作系统一致的外观界面。抽象工厂模式也是在软件开发中最常用的设计模式之一。

优点:

缺点:

增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。

工厂模式的退化

当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。

来源地址:https://blog.csdn.net/m0_65260253/article/details/127909823

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯