目录

一、概述

1.1 为什么会工厂模式

二、 简单工厂模式

2.1 简单工厂模式的类图

2.2 简单工厂模式示列

2.3 优缺点

三 、工厂方法

3.1 工厂方法模式解决和什么问题

3.2 工厂方法模式实例

3.4 工厂方法模式的优点和缺点

四、 抽象工厂模式

4.1 场景

4.2 抽象工厂模式概念

4.3 来看下具体的实例

4.4 抽象工厂模式的优点和缺点

五、 三种工厂模式之间的关系


一、概述

1.1 为什么会有工厂模式

如果使用new来创建对象,简单的对象来好。如果是复杂的对象,有很多的细节(一些成员变量的初始化),这个时候我们就需要了解对象的细节。其实大多数时候我们只是将这个对象拿来用就可以了,并不需要关注那么多细节。

使用new 创建对象的缺点:

  • 客户端需要了解对象的内部细节。

  • 不符合面向接口编程原则,需要知道具体的实现类的细节。

  • 耦合在客户端,万一对象需要做扩展。100 个客户端使用该对象,100 个客户端都需要做修改。

二、 简单工厂模式

2.1 简单工厂模式的类图

  • Api: 接口定义客户端需要的功能
  • ApiImpl1/2: 具体的实现类
  • Factory: 负责创建具体的实现类
  • Client: 客户端,只需要知道 Api。 和 Factory

2.2 简单工厂模式示列

我们用培训课程场景,来示范简单工厂模式。

1 先定义客户端需要的功能API 接口: ICourse

public interface ICourse {/*** 课程内容*/public void content();
}

2 具体的两个实现类 JavaCourse  和 PythonCourse

/*** Java课程*/
public class JavaCourse implements ICourse {public void content() {System.out.println("java课程");}
}/*** Pythod课程*/
public class PythonCourse implements ICourse {public void content() {System.out.println("Python课程");}
}

3 工厂类  CourseFactory

/*** 创建课程工厂*/
public class CourseFactory {public static ICourse createCourse(int type){if (type == 1) {return new JavaCourse();} else if (type == 2) {return new PythonCourse();}return null;}
}

4 客户端使用 Client

public class Client {public static void main(String[] args) {// 不需要知道实现类的创建细节ICourse javaCourse = CourseFactory.createCourse(1);javaCourse.content();ICourse pythonCourse = CourseFactory.createCourse(2);pythonCourse.content();}
}

2.3 优缺点

优点:(工厂模式解决了哪些问题)

  • 隐藏了创建对象的细节
  • 客户端与具体实现类解耦,符合面向 接口编程。

缺点:

  • 工厂类的职责太多。
  • 不符合单一职责。

怎么理解缺点呢?

后期如果再增加怎得课程,增加 if else 判断。 就需要修改 CourseFactory。 造成CourseFactory 代码越来越臃肿, 不利于维护, 不符合开闭原则。

三 、工厂方法

3.1 工厂方法模式解决和什么问题

上面谈到简单工厂模式的缺点:

1 工厂类的职责太多。2 不符合单一职责。3 新增复杂类型时候,不符合开闭原则。

工厂方法模式就是用来解决上面的缺点的,并且功能更加强大。

我们先来看下工厂方法模式的定义:

定义一个用于创建对象的抽象类,让子类决定实例化哪一个类,使一个类的实例化延迟到子类。

UML类图

从UML类图中可以看出 产品和工厂是平行的关系, 有几个产品实现类,就有几个工厂类。

Factory: 抽象类,里面定义一个抽象方法。创建具体的产品,延迟到子类实现。

Factory1/2: 具体创建实例的工厂。

Api: 产品接口。

Apilmpl1/2: 具体产品的实现。


思考下,如果现在我们要新增一个产品该怎么做呢?

我们需要新增一个产品实现类 ApiImpl3 和 工厂实现类 Factory3 就可以了,不需要去修改原来的Factory类。这样就解决了简单工厂模式的缺点: 符合开闭原则,单一职责原则。

3.2 工厂方法模式实例

还是以创建课程实例为列子。

课程接口,和课程实现类和简单工厂没有差别。这里就不做冗余的创建。主要看下工厂类的改造。

1 抽象工厂类 CourseFactory
/*** 抽象工厂父类*/
public abstract class CourseFactory {/*** 工厂方法,具体实例化对象由子类实现* @return 具体实例*/protected abstract ICourse createCourse();public ICourse getCourse() {ICourse course = createCourse();System.out.println("设置复杂属性...");return course;}
}

protected abstract ICourse createCourse(); 延迟到子类实现,创建具体的实例。该方法一般不供外部调用。可以理解为钩子函数。

外部使用 getCourse() 方法。在里面可以进行一些公共的操作。比如 设置一些公共复杂的属性。

2 具体工厂实现类

/*** java 课程工厂*/
public class JavaCourseFactory extends CourseFactory {protected ICourse createCourse() {return new JavaCourse();}
}/*** python 课程工厂*/
public class PythonCourseFactory extends CourseFactory {protected ICourse createCourse() {return new PythonCourse();}
}

3 Client端使用

public class Client {public static void main(String[] args) {CourseFactory javaCourseFactory = new JavaCourseFactory();javaCourseFactory.getCourse().content();System.out.println("----------------------------------");CourseFactory pythonCourseFactory = new PythonCourseFactory();pythonCourseFactory.getCourse().content();}
}

运行结果

3.4 工厂方法模式的优点和缺点

优点:

  • 扩展方便,新增产品类。不需要修改工厂方法。符合开闭原则
  • 工厂类符合单一职责原则,维护方便。
  • 适用于创建一些实例化过程比较复杂的对象。

缺点:

  • 类太多,可以看出,工厂方法模式比简单工厂模式 多出了 很多 具体的工厂类。 增加了复杂度。
  • 增加了系统的抽象性和理解难度。

四、 抽象工厂模式

4.1 场景

生活中一个常见的列子,组装电脑。 组装电脑需要 CPU 和 主板。先想一下怎么来组装一台电脑呢,简单一点假设组装电脑只需要CPU 和 主板。首先,我们需要CPU 和 主板,然后再将CPU和主板 交给装机工程师进行组装。怎么生产CPU和主板呢,通过上面简单工厂模式和工厂方法模式的学习,我们很自然的想到了用工厂模式创建,代码如下。

1 cpu 接口 和 cpu实现类

/*** CPU*/
public interface ICPU {/*** 计算能力*/public void calcuator();
}public class IntelCPU implements ICPU {/*** 引脚个数*/private int pins;public IntelCPU(int pins) {this.pins = pins;}public void calcuator() {System.out.println("IntelCPU 计算能力!引脚个数:" + this.pins);}
}/*** AMDcpu*/
public class AmdCPU implements ICPU {private int pins;public AmdCPU(int pins) {this.pins = pins;}public void calcuator() {System.out.println("AmdCpu 计算能力!引脚个数:" + this.pins);}
}

2 主板 和 主板实现类

/*** 主板*/
public interface IMainboard {/*** 示意方法,安装cpu*/public void installCPU();
}public class GAMainboard implements IMainboard{/*** 主板卡槽*/private int  cpuHoles;public GAMainboard(int cpuHoles) {this.cpuHoles = cpuHoles;}public void installCPU() {System.out.println("GAMainboard 安装Cpu, 主板卡槽个数:" + this.cpuHoles);}
}/*** 微星主板*/
public class MSIMainboard implements IMainboard{/*** 主板卡槽*/private int  cpuHoles;public MSIMainboard(int cpuHoles) {this.cpuHoles = cpuHoles;}public void installCPU() {System.out.println("MSIMainboard 安装Cpu, 主板卡槽个数:" + this.cpuHoles);}
}

3 采用简单工厂模式,需要两个工厂

public class CPUFactory {/*** 根据type创建cpu* @param type 0 Intel 1 Amd* @return cpu具体实例*/public static ICPU createCpu(int type) {if (type == 0) {return new IntelCPU(1099);} else {return new AmdCPU(899);}}
}public class MainboardFactory {/*** 根据type创建主板* @param type 0 GA 1 MSI* @return 主板具体实例*/public static IMainboard createMainboard(int type) {if (type == 0) {return new GAMainboard(1099);} else {return new MSIMainboard(899);}}
}

4 装机工程师

/*** 组装电脑*/
public class ComputerEnginer {private ICPU cpu;private IMainboard mainboard;public void assembleComputer(int cpuType, int mainboardType) {// 准备cpu 和 主板prepareHardwares(cpuType, mainboardType);// 组装完成}/*** 准备cpu 和 主板** @param cpuType       cpu 类型* @param mainboardType 主板类型*/private void prepareHardwares(int cpuType, int mainboardType) {cpu = CPUFactory.createCpu(cpuType);mainboard = MainboardFactory.createMainboard(mainboardType);// 测试cpu.calcuator();mainboard.installCPU();}
}

5 客户端使用

public class Client {public static void main(String[] args) {ComputerEnginer computerEnginer = new ComputerEnginer();computerEnginer.makeComputer(1,0);}
}

结果

有何问题 ?

可以看到结果中 Cpu 和 主板卡槽的个数并不匹配。装机电脑其实是有问题的。所以客户端在选择组件的时候就需要考虑到 cpu 和主板之间的以来关系,才能正确的创造出电脑。但是客户端可能并不知道具体的匹配关系。那怎么解决这个问题呢 ?

这个时候我们可以提供几套选择的套餐空客户端选择。套餐里面已经定义好了cpu 和 主板之间的关系。对应的解决方案就是抽象工厂模式。 

4.2 抽象工厂模式概念

定义:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体实现类。

先来看下UML类图

AbstractFactory: 抽象工厂,里面定义了创建产品的抽象方法。

ConcreteFactory1/2: 具体的工厂,相当于前面所说的套餐。

IProductA/B: 产品接口

IProductA/B(1,2): 产品具体实现类。 产品A 和 产品B 之间有相应的对应关系。需要选对匹配。

4.3 来看下具体的实例

基于前面提高的 cpu 和 主板来进行实例。 cpu 和 主板的 接口和实现前面有,这里不在冗余创建。 主要是将工厂类进行改造,两面所创建按的两个静态工厂就不需要了。

1 AbstractFactory 和 实现类

/*** 抽象工厂模式。抽象工厂*/
public interface AbstractFactory {public ICPU createCPU();public IMainboard createMainboard();}/*** 装机方案一*/
public class Schem1 implements AbstractFactory {public ICPU createCPU() {return new IntelCPU(1099);}public IMainboard createMainboard() {return new GAMainboard(1099);}
}/*** 装机方案二*/
public class Schem2 implements AbstractFactory {public ICPU createCPU() {return new AmdCPU(899);}public IMainboard createMainboard() {return new MSIMainboard(899);}
}
2 装机工程师
/*** 组装电脑*/
public class ComputerEnginer {private ICPU cpu;private IMainboard mainboard;public void makeComputer(AbstractFactory scheme) {// 准备cpu 和 主板prepareHardwares(scheme);// 组装完成}/*** 准备cpu 和 主板** @param scheme 装机方案*/private void prepareHardwares(AbstractFactory scheme) {cpu = scheme.createCPU();mainboard = scheme.createMainboard();// 测试cpu.calcuator();mainboard.installCPU();}
}

这里在创建cpu  和 主板的时候,直接使用 AbstractFactory  具体实现类,方案 scheme进行创建就可以了,保证了对应关系。

3 客户端使用

public class Client {public static void main(String[] args) {AbstractFactory schem1 = new Schem1(); // 方案一AbstractFactory schem2 = new Schem2(); // 方案二ComputerEnginer computerEnginer = new ComputerEnginer();computerEnginer.makeComputer(schem1);System.out.println("--------------------------切换装机方案-----------------");computerEnginer.makeComputer(schem2);}
}

客户端选择的时候,只需要选择具体的方案就可以了,不需要单独选择 cpu 或 主板。不需要知道它们之间的对应关系。

结果:

4.4 抽象工厂模式的优点和缺点

优点:

  • 分离了接口和实现
  • 维护了系列产品之间的依赖关系。使得产品切换容易。

缺点:

  • 不太容易扩展产品,比如组装笔记本还需要配件内存。那么 AbstractFactry 和 具体的工厂类,还有装机工程师类都需要做更改。

五、 三种工厂模式之间的关系

工厂方法模式, 如果就在具体的工厂父类里面创建实例就退化为 简单工厂模式。

抽象工厂模式,如果产品族中只有一个产品,那么就退化为工厂方法模式。

简单工厂模式 ---> 工厂方法模式---->抽象工厂模式。 解决的问题越来越复杂。

在实际的运用中,根据具体的业务场景选择合适的即可。

参考资料

书籍:<<研磨设计模式>>  陈臣,王斌 著

博客:https://blog.csdn.net/varyall/article/details/82355964

设计模式(工厂模式)相关推荐

  1. Java设计模式-工厂模式(3)抽象工厂模式

    在Java设计模式-工厂模式(2)工厂方法模式 我们知道了工厂方法模式解决了简单工厂模式中的缺陷,做到了满足开闭原则,但是时代是进步的,进而又产生新的问题,工厂难道只能生产一种东西吗.我们所见到的工厂 ...

  2. Java设计模式-工厂模式(2)工厂方法模式

    在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而"工厂方法模式"是对简单工厂模式的进一步抽象化,其好处是可以使系统在不 ...

  3. Java设计模式-工厂模式(1)简单工厂模式

    Java设计模式-工厂模式(1)简单工厂模式 一.前言 1)例子 2)类图关系 3)代码实现 二.简单工厂模式 2.1.概述: 2.2.类图关系: 2.3.代码修改: 2.4.优缺点 2.5.扩展-简 ...

  4. 设计模式---工厂模式

    设计模式---工厂模式 工厂方法模式 概述:工厂方法模式中抽象工厂负责定义创建对象的接口,具体创建工作由继承抽象工厂的具体类实现. 优点:客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新 ...

  5. java设计模式工厂模式_Java中的工厂设计模式

    java设计模式工厂模式 Welcome to the Factory Design Pattern in Java tutorial. Factory Pattern is one of the C ...

  6. java设计模式工厂模式_Java中的复合设计模式

    java设计模式工厂模式 Composite pattern is one of the Structural design pattern. Composite design pattern is ...

  7. java设计模式工厂模式_Java中的桥梁设计模式

    java设计模式工厂模式 Today we will look into Bridge Design Pattern in java. When we have interface hierarchi ...

  8. java设计模式工厂模式_Java中的外观设计模式

    java设计模式工厂模式 Facade Design Pattern is one of the Structural design patterns (such as Adapter pattern ...

  9. 设计模式-工厂模式(学习)

    设计模式-工厂模式(学习) 在程序的世界里,就像射雕英雄传一样,我们的技能就像是武功一样,我们只有不断去学习练习才能有机会像郭靖一样成为"天下第一". 我认为技能和武功是很类似的, ...

  10. 设计模式-工厂模式的3中不同实现[JAVA]

    设计模式-工厂模式的3中不同实现[JAVA] 工厂模式简介 In Factory pattern, we create object without exposing the creation log ...

最新文章

  1. 合并多个文本文件方法
  2. hibernate继承关系映射方法(三)--每个具体类一张表TPC
  3. centos 7.9密码改密钥登陆
  4. C++struct和class区别
  5. 养心灵,才能美容颜,拥有好日子(图)
  6. Sequelize Model
  7. 《R语言实战》读书笔记--学习张丹日志
  8. 德州扑克AI--Programming Poker AI(译)
  9. (Greedy approach)Find longest word in dictionary that is a subsequence of a given string
  10. 寒冬中的一次优雅起舞
  11. Unity粒子特效系列-毒液喷射预制体做好了,unitypackage包直接用 - 上
  12. Task异步编程,刨根到底
  13. 国产DeFi,困在币价里
  14. PB 数据窗口数据导入Excel, 如果存在则追加,不存在则创建。
  15. 酷睿i5 1155g7相当于什么水平 i51155g7属于哪个档次
  16. PC与Android通过USB连接进行Socket通信
  17. 城市应急指挥系统建设方案(智慧应急综合管理平台)
  18. 中国移动MobileMarket重点支持机型信息-12月24日
  19. 用74LS153D画出三人表决电路
  20. 成都榆熙电子商务有限公司:拼多多爆款产品的表现形式有哪些?

热门文章

  1. 删除的备忘录怎么恢复
  2. 通过AWS云平台 构建云上勒索病毒防护体系,轻松保护数据完整性
  3. php图片不显示怎么处理,如何解决php图片因存在错误而无法显示
  4. 什么是ssl证书,ssl证书有哪几种类型?
  5. SpringBoot控制配置类加载顺序
  6. oracle 正序 倒序 排列
  7. THinkphp5.0开源个人博客系统-优优博客系统 v2.3
  8. Occupancy Flow: 4D Reconstruction by Learning Particle Dynamics(1)
  9. HTTP断点续传以及缓存问题
  10. 微信大会有哪些看点?