工厂方法模式
时间:2022-07-24
本文章向大家介绍工厂方法模式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
工厂方法模式
工厂方法模式Factory Method Pattern
又称为工厂模式,也叫虚拟构造器Virtual Constructor
模式或者多态工厂Polymorphic Factory
模式,它属于类创建型模式,在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
描述
简单工厂模式有一个问题,类的创建依赖工厂类,也就是说如果想要拓展程序,必须对工厂类进行修改,而工厂方法模式就是将具体的创建过程交给专门的工厂子类去完成,即将产品类的实例化操作延迟到工厂子类中完成,由此可以不必再去修改工厂类,而只需要定义实现工厂的子类即可。
模式分析
工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
模式结构
-
Product
:抽象产品。 -
ConcreteProduct
:具体产品。 -
Factory
:抽象工厂。 -
ConcreteFactory
:具体工厂。
优点
- 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
- 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
- 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
缺点
- 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到反射等技术,增加了系统的实现难度。
实现
工厂方法模式的本意是将实际创建对象的工作推迟到子类中,这样核心类就变成了抽象类,但是在JavaScript
中很难像传统面向对象那样去实现创建抽象类,所以在JavaScript
中只需要参考其核心思想即可。
class Shape { // 产品基类
say(){
console.log(this.name);
}
}
class Rectangle extends Shape{ // 长方形产品
constructor(){
super();
this.name = "Rectangle";
}
}
class Square extends Shape{ // 正方形产品
constructor(){
super();
this.name = "Square";
}
}
class Circle extends Shape{ // 圆形产品
constructor(){
super();
this.name = "Circle";
}
}
class Factory{ // 工厂基类
getProduct(){}
}
class RectangleFactory extends Factory{
constructor(){
super();
}
getProduct(){
return new Rectangle();
}
}
class SquareFactory extends Factory{
constructor(){
super();
}
getProduct(){
return new Square();
}
}
class CircleFactory extends Factory{
constructor(){
super();
}
getProduct(){
return new Circle();
}
}
var rectangle = (new RectangleFactory).getProduct();
rectangle.say(); // Rectangle
var square = (new SquareFactory).getProduct();
square.say(); // Square
var circle = (new CircleFactory).getProduct();
circle.say(); // Circle
// 组装图形的例子 // 假如需要组装三个图形
class Shape { // 形状基类
say(){
console.log(this.name);
}
}
class Rectangle extends Shape{ // 长方形
constructor(){
super();
this.name = "Rectangle";
}
}
class Square extends Shape{ // 正方形
constructor(){
super();
this.name = "Square";
}
}
class Circle extends Shape{ // 圆形
constructor(){
super();
this.name = "Circle";
}
}
class Combination{
constructor(rectangle, square, circle){
console.log(`Combination: ${rectangle.name} ${square.name} ${circle.name}`);
}
}
// 直接组装 调用者只需要一个组合完成的图形,而为了组装需要分别实例化三个形状,耦合度太高
(function(){
var rectangle = new Rectangle();
var square = new Square();
var circle = new Circle();
new Combination(rectangle, square, circle);
})();
// 使用工厂 隐藏具体实现细节 降低耦合度
class CombinationFactory{
getProduct(){
var rectangle = new Rectangle();
var square = new Square();
var circle = new Circle();
return new Combination(rectangle, square, circle);
}
}
(function(){
var combination = (new CombinationFactory).getProduct();
})();
每日一题
https://github.com/WindrunnerMax/EveryDay
参考
https://blog.csdn.net/carson_ho/article/details/52343584
https://wiki.jikexueyuan.com/project/java-design-pattern/factory-pattern.html
https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/factory_method.html
- 在Selenium Webdriver中使用XPath Contains、Sibling函数定位
- Python多线程Selenium跨浏览器测试
- Python Selenium设计模式-POM
- 基于Excel参数化你的Selenium2测试
- 创建你的第一个webdriver python代码
- Python Selenium Webdriver安装手册
- 工具篇 - HTTP协议报文结构及示例03
- 工具篇 - JMeter目录及关键配置分析02
- python unittest之加载及跳过测试方法和示例
- python unittest之异常测试
- python unittest之断言及示例
- python unittest关键API说明及示例
- 性能测试必备监控技能linux篇14
- JMeter函数和变量11
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Maven配置多仓库无效?来看看这篇文章
- Spring Boot启动slf4j提示找不到weblogic.xml日志异常
- Angular 应用的DevDependencies
- 轻量级服务网格 - osm
- 漫画:设计模式之 “外观模式”
- 使用 Zotero 在 Markdown 中优雅处理参考文献
- Mybatis plus自动生成业务代码
- 功能强大的CD工具 - flagger
- Swift defer
- MySQL 最佳实践:CPU 100%,MySQL 到底在干什么
- 【译】Flutter 1.20 发布
- 算法面试题:一个List,要求删除里面的男生,不用Linq和Lamda,求各种解,并说明优缺点!
- Angular CLI创建的项目文件用途一栏
- [888]python内置函数vars()|dir()|locals()
- Mdnice,一种记录知识的新方式