JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C++,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代表全部的正确,特此声明。若读者需要了解设计模式目录、原则、设计变化方向,环境相关等信息请查看设计模式开篇。
一、UML类图
参与者:
1.1 AbstractFactory
声明一个创建抽象产品对象的操作接口。
1.2 ConcreteFactory
实现创建具体产品对象的操作。
1.3 AbstractProduct
为一类产品对象声明一个接口。
1.4 ConcreteProduct
定义一个将被相应的具体工厂创建的产品对象。
1.5 Client
仅使用由AbstractFactory和AbstractProduct类声明的接口。
二、场景、意图
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
三、适用性
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
四、有点和缺点
- 它分离了具体的类AbstractFactory模式帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和过程,它将客户与类的实现分离。客户通过它们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。
- 它使得易于交换产品系列一个具体工厂类在一个应用中仅出现一次—即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置,这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。在我们的用户界面的例子中,我们仅需转换到相应的工厂对象并重新创建接口,就可实现从Motif窗口组件转换为PresentationManager窗口组件。
- 它有利于产品的一致性当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。而AbstractFactory很容易实现这一点。
- 难以支持新种类的产品难以扩展抽象工厂以生产新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及AbstractFactory类及其所有子类的改变。我们会在实现一节讨论这个问题的一个解决办法。
五、示例代码
5.1 动机
考虑一个支持多种视感(look-and-feel)标准的用户界面工具包,例如Motif(Motif 诞生于 1980 年代 Unix 工作站崛起的时代,由 DEC 和惠普等公司联合开发作为 X Window System 的一个通用的用户界面工具箱,后成为 Common Desktop Environment(CDE)桌面环境的基础构件。)和 Mac(Macintosh(简称Mac)是苹果公司自1984年起开发的个人消费型计算机,包含如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro等计算机。使用独立的macOS系统,最新的macOS系列基于NeXT系统开发,不支持兼容。是一套完备而独立的操作系统。) 。不同的视感风格为诸如滚动条、窗口和按钮等用户界面“窗口组件”定义不同的外观和行为。为保证视感风格标准间的可移植性,一个应用不应该为一个特定的视感外观硬编码它的窗口组件。
5.2 示例UML
目录结构:
5.3 AbstractFactory(WidgetFactory)
此处的抽象工厂是WidgetFactory类:
import scrollBar from '../ScrollBar/ScrollBar.js';
import Window from '../Window/Window.js';
export default class WidgetFactory {
scrollBar=new scrollBar();
window=new Window();
constructor() {
}
CreateScrollBar() {
}
CreateWindow() {
}
}
5.4 ConcreteFactory
具体的创建工厂为:MotiWidgetFactory和PMWidgetFactory(PM理解成Moti、Mac外的另一种系统界面)
MotiWidgetFactory类:
import WidgetFactory from '../WidgetFactory.js';
import MotiScrollBar from '../../ScrollBar/impl/MotiScrollBar.js';
import MotiWindow from '../../Window/impl/MotiWindow.js';
export default class MotiWidgetFactory extends WidgetFactory{
constructor() {
super();
}
CreateScrollBar() {
this.scrollBar=new MotiScrollBar();
return this.scrollBar;
}
CreateWindow() {
this.window=new MotiWindow();
return this.window;
}
}
PMWidgetFactory类:
import WidgetFactory from '../WidgetFactory.js';
import PMScrollBar from '../../ScrollBar/impl/PMScrollBar.js';
import PMWindow from '../../Window/impl/PMWindow.js';
export default class PMWidgetFactory extends WidgetFactory {
constructor() {
super();
}
CreateScrollBar() {
this.scrollBar=new PMScrollBar();
return this.scrollBar;
}
CreateWindow() {
this.window=new PMWindow();
return this.window;
}
}
5.5 AbstractProduct
此处的抽象产品类是:Window
export default class Window{
constructor() {
}
movewindow()
{
}
close()
{
}
fl()
{
console.log(` Window fl `);
}
fg()
{
console.log(` Window fg `);
}
}
5.6 ConcreteProduct
具体产品类:MotiWindow和PMWindow
MotiWindow
import Window from '../Window.js';
export default class MotiWindow extends Window{
constructor() {
super();
console.log(` MotiWindowMoti be create `);
}
movewindow()
{
console.log(` MotiWindowMoti movewindow `);
}
close()
{
console.log(` MotiWindowMoti close `);
}
fg()
{
console.log(` MotiWindowMoti fg `);
}
}
PMWindow
import Window from '../Window.js';
export default class PMWindow extends Window{
constructor() {
super();
console.log(` PMWindow be create `);
}
movewindow()
{
console.log(` PMWindow movewindow `);
}
close()
{
console.log(` PMWindow be close `);
}
fg()
{
console.log(` PMWindow fg `);
}
}
5.7 Client
import WidgetFactory from './WidgetFactory/WidgetFactory.js';
// import PMWidgetFactory from './WidgetFactory/impl/PMWidgetFactory.js';
import MotiWidgetFactory from './WidgetFactory/impl/MotiWidgetFactory.js';
import ScrollBar from './ScrollBar/ScrollBar.js';
import Window from './Window/Window.js';
export default class Client{
main(){
// let pmFactory =new PMWidgetFactory();//WidgetFactory
// pmFactory.CreateScrollBar();
// let window= pmFactory.CreateWindow();
// window.movewindow();
// window.close();
let pmFactory =new MotiWidgetFactory();//WidgetFactory
pmFactory.CreateScrollBar();
let window=pmFactory.CreateWindow();//Window
window.movewindow();
window.close();
window.fl();
window.fg();
}
}
5.8 测试HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="module" >
import Client from './Client.js';
let cl=new Client();
cl.main()
</script>
</head>
<body>
</body>
</html>
测试结果:
MotiScrollBar.js:6 MotiScrollBar be create
MotiWindow.js:7 MotiWindowMoti be create
MotiWindow.js:11 MotiWindowMoti movewindow
MotiWindow.js:15 MotiWindowMoti close
Window.js:14 Window fl
MotiWindow.js:19 MotiWindowMoti fg
六、源代码下载
下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw
提取码:q2ut