设计模式(工厂模式)
目录
一、概述
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
设计模式(工厂模式)相关推荐
- Java设计模式-工厂模式(3)抽象工厂模式
在Java设计模式-工厂模式(2)工厂方法模式 我们知道了工厂方法模式解决了简单工厂模式中的缺陷,做到了满足开闭原则,但是时代是进步的,进而又产生新的问题,工厂难道只能生产一种东西吗.我们所见到的工厂 ...
- Java设计模式-工厂模式(2)工厂方法模式
在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而"工厂方法模式"是对简单工厂模式的进一步抽象化,其好处是可以使系统在不 ...
- Java设计模式-工厂模式(1)简单工厂模式
Java设计模式-工厂模式(1)简单工厂模式 一.前言 1)例子 2)类图关系 3)代码实现 二.简单工厂模式 2.1.概述: 2.2.类图关系: 2.3.代码修改: 2.4.优缺点 2.5.扩展-简 ...
- 设计模式---工厂模式
设计模式---工厂模式 工厂方法模式 概述:工厂方法模式中抽象工厂负责定义创建对象的接口,具体创建工作由继承抽象工厂的具体类实现. 优点:客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新 ...
- java设计模式工厂模式_Java中的工厂设计模式
java设计模式工厂模式 Welcome to the Factory Design Pattern in Java tutorial. Factory Pattern is one of the C ...
- java设计模式工厂模式_Java中的复合设计模式
java设计模式工厂模式 Composite pattern is one of the Structural design pattern. Composite design pattern is ...
- java设计模式工厂模式_Java中的桥梁设计模式
java设计模式工厂模式 Today we will look into Bridge Design Pattern in java. When we have interface hierarchi ...
- java设计模式工厂模式_Java中的外观设计模式
java设计模式工厂模式 Facade Design Pattern is one of the Structural design patterns (such as Adapter pattern ...
- 设计模式-工厂模式(学习)
设计模式-工厂模式(学习) 在程序的世界里,就像射雕英雄传一样,我们的技能就像是武功一样,我们只有不断去学习练习才能有机会像郭靖一样成为"天下第一". 我认为技能和武功是很类似的, ...
- 设计模式-工厂模式的3中不同实现[JAVA]
设计模式-工厂模式的3中不同实现[JAVA] 工厂模式简介 In Factory pattern, we create object without exposing the creation log ...
最新文章
- 合并多个文本文件方法
- hibernate继承关系映射方法(三)--每个具体类一张表TPC
- centos 7.9密码改密钥登陆
- C++struct和class区别
- 养心灵,才能美容颜,拥有好日子(图)
- Sequelize Model
- 《R语言实战》读书笔记--学习张丹日志
- 德州扑克AI--Programming Poker AI(译)
- (Greedy approach)Find longest word in dictionary that is a subsequence of a given string
- 寒冬中的一次优雅起舞
- Unity粒子特效系列-毒液喷射预制体做好了,unitypackage包直接用 - 上
- Task异步编程,刨根到底
- 国产DeFi,困在币价里
- PB 数据窗口数据导入Excel, 如果存在则追加,不存在则创建。
- 酷睿i5 1155g7相当于什么水平 i51155g7属于哪个档次
- PC与Android通过USB连接进行Socket通信
- 城市应急指挥系统建设方案(智慧应急综合管理平台)
- 中国移动MobileMarket重点支持机型信息-12月24日
- 用74LS153D画出三人表决电路
- 成都榆熙电子商务有限公司:拼多多爆款产品的表现形式有哪些?