抽象工厂模式
抽象工厂模式
抽象工厂模式Abstract Factory
是通过对类的工厂抽象使其业务用于对产品类簇的创建,而不仅仅是负责创建某一类产品的实例,抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类,抽象工厂模式又称为Kit
模式,属于对象创建型模式。
描述
在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下一个具体工厂中只有一个工厂方法或者一组重载的工厂方法,但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象,当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。
抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。
模式结构
* AbstractFactory
: 抽象工厂。
* ConcreteFactory
: 具体工厂。
* AbstractProduct
: 抽象产品。
* Product
: 具体产品。
优点
* 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
* 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
* 增加新的具体工厂和产品族很方便,无须修改已有系统,符合开闭原则。
缺点
* 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
* 开闭原则的倾斜性,增加新的工厂和产品族容易,增加新的产品等级结构麻烦。
实现
class Shape { // 形状基类
draw(){
console.log(this.shape);
}
}
class Rectangle extends Shape{ // 长方形
constructor(){
super();
this.shape = "Rectangle";
}
}
class Square extends Shape{ // 正方形
constructor(){
super();
this.shape = "Square";
}
}
class Circle extends Shape{ // 圆形
constructor(){
super();
this.shape = "Circle";
}
}
class Color { // 颜色基类
fill(){
console.log(this.color);
}
}
class Red extends Color{ // 红色
constructor(){
super();
this.color = "Red";
}
}
class Green extends Color{ // 绿色
constructor(){
super();
this.color = "Green";
}
}
class Blue extends Color{ // 蓝色
constructor(){
super();
this.color = "Blue";
}
}
class Factory{ // 工厂基类 模拟抽象方法
getShape(){
throw new Error("Abstract method cannot be called");
}
getColor(){
throw new Error("Abstract method cannot be called");
}
}
class ShapeFactory extends Factory{ // 形状工厂
getShape(shape){
switch (shape.toLowerCase()) {
case "rectangle":
return new Rectangle();
case "square":
return new Square();
case "circle":
return new Circle();
default:
throw new Error("参数错误");
}
}
getColor(){
return null;
}
}
class ColorFactory extends Factory{ // 颜色工厂
getShape(){
return null;
}
getColor(color){
switch (color.toLowerCase()) {
case "red":
return new Red();
case "green":
return new Green();
case "blue":
return new Blue();
default:
throw new Error("参数错误");
}
}
}
class FactoryGenerator{ // 工厂生成器类 通过传递形状或颜色来获取工厂
static getFactory(choice){
choice = choice.toLowerCase();
if(choice === "shape") {
return new ShapeFactory();
}else if(choice === "color"){
return new ColorFactory();
}
throw new Error("参数错误");
}
}
(function(){
var shapeFactory = FactoryGenerator.getFactory("shape");
var colorFactory = FactoryGenerator.getFactory("color");
shapeFactory.getShape("rectangle").draw();
shapeFactory.getShape("square").draw();
shapeFactory.getShape("circle").draw();
colorFactory.getColor("red").fill();
colorFactory.getColor("green").fill();
colorFactory.getColor("blue").fill();
})();
每日一题
https://github.com/WindrunnerMax/EveryDay
参考
https://www.runoob.com/design-pattern/abstract-factory-pattern.html
https://wiki.jikexueyuan.com/project/java-design-pattern/abstract-factory-pattern.html
https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/abstract_factory.html
- 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 数组属性和方法
- Python 句法错误:"SyntaxError: invalid character in identifier",原因及解决方法
- Python3 多线程问题:ModuleNotFoundError: No module named 'thread',原因及解决办法。
- 文件传输和秒传
- 关于数据库的各种备份与还原姿势详解
- Python 技术篇-多线程的2种创建方法,多线程的简单用法,快速上手。
- Python 技术篇-调用浏览器访问指定网页,一行代码实现。非Selenium。
- 数据库热备份神器 - XtraBackup
- Python 技术篇-读取文件,将内容保存dict字典中。去掉字符串中的指定字符方法。dict字典的遍历。
- PyQt5 技术篇-plainTextEdit控件获得文本内容方法、设置文本内容方法。
- PyQt5 技术篇-鼠标移动控件显示提示,Qt Designer控件提示设置方法。
- PyQt5 技术篇-窗口名、窗口图标的设置方法。
- 101个shell脚本
- PyQt5 图片兼容性问题:"libpng warning: bKGD: invalid.",原因及解决办法。
- 编程语言经典小例题—Python版【持续更新】
- Python+selenium 自动化-切换窗口页签、切换iframe框架。确定页面是否包含iframe方法。