抽象工厂模式(Abstract Factory)
抽象工厂模式(Abstract Factory)
抽象工厂模式(Abstract Factory)[Kit]
意图:提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。
应用:用户界面工具包。
模式结构:
心得:
工厂方法把生产产品的方式封装起来了,但是一个工厂只能生产一类对象,当一个工厂需要生产多类产品的时候,就需要使用抽象工厂了。抽象工厂(AbstractFactory)类定义了一组标准的实现接口,这些接口一般都是和具体的产品类继承层次对应的。如createProductA接口只能生产抽象产品类(AbstratctProductA)的子类产品,因此抽象工厂的具体实现类之间的关系就是个生产了一批不同产品族的组合。这样通过抽象工厂模式可以方便的更换产品族,代码修改的代价只需要更换一个具体的工厂对象就可以了。因此直观上可以把抽象工厂看作一组工厂方法,它的每一个接口都可以提取出一个单独的工厂方法。不过抽象工厂除了反映出这些含义外,还隐含着多类产品之间有种内在的联系,如按钮、菜单、滚动条都是GUI组件。
举例:
对于可以随意更换GUI组件库的需求,抽象工厂就可以完成类似的功能。抽象工厂类(AbstractFactory)封装了GUI组件库必须提供的接口,如创建按钮、菜单、滚动条等。GUI组件类会根据不同的窗口系统而派生具体的组件类,实现抽象工厂的具体类具体工厂类会根据不同的窗口系统选择对应的组件进行生产。这样当更换窗口系统的时候,只需要更换工厂类就能方便的实现运行时窗口系统的更换。按照这样的描述,我们可以实现的C++代码如下:
//产品类继承层次
class Button
{
public:
virtual void click()=0;
virtual ~Button(){}
};
class WindowsButton:public Button
{
public:
virtual void click()
{
cout<<"单击了Windows按钮"<<endl;
}
};
class MacButton:public Button
{
public:
virtual void click()
{
cout<<"单击了Mac按钮"<<endl;
}
};
class Menu
{
public:
virtual void select()=0;
virtual ~Menu(){}
};
class WindowsMenu:public Menu
{
public:
virtual void select()
{
cout<<"选择了Windows菜单"<<endl;
}
};
class MacMenu:public Menu
{
public:
virtual void select()
{
cout<<"选择了Mac菜单"<<endl;
}
};
//抽象工厂
class GUIFactory
{
public:
virtual Button*createButton()=0;
virtual Menu*createMenu()=0;
virtual ~GUIFactory(){}
};
//具体的工厂
class WindowsGUIFactory:public GUIFactory
{
public:
virtual Button*createButton()
{
return new WindowsButton();
}
virtual Menu*createMenu()
{
return new WindowsMenu();
}
};
class MacGUIFactory:public GUIFactory
{
public:
virtual Button*createButton()
{
return new MacButton();
}
virtual Menu*createMenu()
{
return new MacMenu();
}
};
这里代码中类的继承接口和图中相同,只是为了方便理解,修改了一下类的名字。如果我们使用这段代码创建组件,就会这么写了:
GUIFactory*factory=new WindowsGUIFactory();//创建工厂
Button*btn=factory->createButton();//创建组件
Menu*menu=factory->createMenu();
btn->click();//调用组件函数
menu->select();
delete btn;
delete menu;
delete factory;
从代码中看出我们无法看到看到具体创建的组件,因为我们只需要用抽象类Button、Menu使用标准的接口就可以了,具体的实现被工厂封装起来了。如果我们要更换所有的一批组件的话,只需要修改第一行代码,换一个工厂就可以了。
参考文章:http://blog.csdn.net/zhxue123/article/details/5816397
- 模板语言
- Django 相关
- 装饰器进阶
- P2894 [USACO08FEB]酒店Hotel
- 深入理解计算机系统读书笔记之第一章:漫游
- 【实战】工控网络协议模糊测试:用peach对modbus协议进行模糊测试
- 【Django错误】OSError: raw write() returned invalid length 14 (should have been between 0 and 7)
- P2234 [HNOI2002]营业额统计
- Python 中格式化字符串 % 和 format 两种方法之间的区别
- [实战]如何在Kali Linux中进行WIFI钓鱼?
- jQuery
- P3369 【模板】普通平衡树(Treap/SBT)
- Django之ORM基础
- P3381 【模板】最小费用最大流
- 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 数组属性和方法
- Android Transform增量编译
- Android自定义lint开发
- 如何持续优化项目内的图片
- XCTF两道web题目的writeup
- 通过Rxjava看Kotlin协程(一)
- Fuzz中的javascript大小写特性
- 通过RxJava看kotlin协程(二)
- Android 黑科技 |Gradle Plugin使用场景
- php5全版本绕过open_basedir读文件脚本
- CameraX 封装二维码扫描组件
- Kotlin拓展函数的真身
- 一个一年没解决的ClassNotFoundException|类加载机制探索
- 我有个大胆的方案可以提高ARouter和WMRouter的编译速度
- Tornado模板对空白字符的处理与解决方案
- View的有效曝光监控(上)|RecyclerView 篇