JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C++,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代表全部的正确,特此声明。若读者需要了解设计模式目录、原则、设计变化方向,环境相关等信息请查看设计模式开篇。
一、UML类图
参与者:
1.1 Component(Graphic)
- 为组合中的对象声明接口。
- 在适当的情况下,实现所有类共有接口的缺省行为。
- 声明一个接口用于访问和管理Component的子组件。
- (可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
1.2 Leaf(Rectangle、Line、Text等)
- 在组合中表示叶节点对象,叶节点没有子节点。
- 在组合中定义图元对象的行为。
1.3 Composite(Picture)
- 定义有子部件的那些部件的行为。
- 存储子部件。
- 在Component接口中实现与子部件有关的操作。
1.4 Client
- 通过Component接口操纵组合部件的对象。
二、意图
将对象组合成树形结构以表示“部分 -整体”的层次结构。Composite使得用户对单个对象 和组合对象的使用具有一致性。
三、适用性
- 你想表示对象的部分-整体层次结构。
- 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
四、示例代码
4.1 动机
在绘图编辑器和图形捕捉系统这样的图形应用程序中,用户可以使用简单的组件创建复杂的图表。用户可以组合多个简单组件以形成一些较大的组件,这些组件又可以组合成更大
的组件。一个简单的实现方法是为Text和Line这样的图元定义一些类,另外定义一些类作为这些图元的容器类(Container)。
然而这种方法存在一个问题:使用这些类的代码必须区别对待图元对象与容器对象,而实际上大多数情况下用户认为它们是一样的。对这些类区别使用,使得程序更加复杂。Composite模式描述了如何使用递归组合,使得用户不必对这些类进行区别。
Composite模式的关键是一个抽象类,它既可以代表图元,又可以代表图元的容器。在图形系统中的这个类就是Graphic,它声明一些与特定图形对象相关的操作,例如Draw。同时它也声明了所有的组合对象共享的一些操作,例如一些操作用于访问和管理它的子部件。子类Line、Rectangle和Text(参见前面的类图)定义了一些图元对象,这些类实现Draw,分别用于绘制直线、矩形和正文。
Picture类定义了一个Graphic对象的聚合。Picture的Draw操作是通过对它的子部件调用Draw实现的,Picture还用这种方法实现了一些与其子部件相关的操作。由于Picture接口与Graphic接口是一致的,因此Picture对象可以递归地组合其他Picture对象。下图是一个典型的由递归组合的Graphic对象组成的组合对象结构。
4.2 示例UML
目录结构:
4.2 Component(Graphic)
export default class Graphic {
childrens = [];
constructor() {
}
Draw() {
}
Add(graphic) {
this.childrens.push(graphic);
}
Remove(index) {
if(index<this.childrens.length)
this.childrens.splice(index, 1);
// 删除 第一个元素 this.#childrens.splice(0, 1);
//第一个参数(0)定义新元素应该被添加(接入)的位置。
//第二个参数(1)定义应该删除多个元素。
//其余参数被省略。没有新元素将被添加。
}
GetChild(index) {
if(index<this.childrens.length)
return this.childrens[index];
}
}
4.3 Leaf(Rectangle、Line、Text等)
import Graphic from '../Graphic.js';
export default class Line extends Graphic {
constructor() {
super();
}
Draw() {
console.log(` Line Draw `);
}
}
import Graphic from '../Graphic.js';
export default class Rectangle extends Graphic {
constructor() {
super();
}
Draw() {
console.log(` Rectangle Draw `);
}
}
import Graphic from '../Graphic.js';
export default class Text extends Graphic {
constructor() {
super();
}
Draw() {
console.log(` Text Draw `);
}
}
4.4 Composite(Picture)
import Graphic from '../Graphic.js';
export default class Picture extends Graphic {
constructor() {
super();
}
Draw() {
console.log(` Picture Draw `);
for(let n=0;n<this.childrens.length;n++)
{
let graphic=this.childrens[n];
graphic.Draw();
}
}
}
4.5 Client
import Graphic from './Graphic/Graphic.js';
import Picture from './Graphic/Picture/Picture.js';
import Line from './Graphic/impl/Line.js';
import Rectangle from './Graphic/impl/Rectangle.js';
import Text from './Graphic/impl/Text.js';
export default class Client{
main(){
let apicture =new Picture();//Graphic
apicture.Add(new Line());
apicture.Add(new Rectangle());
apicture.Add(new Text());
let a2picture =new Picture();//Graphic
apicture.Add(a2picture);
a2picture.Add(new Line());
a2picture.Add(new Text());
apicture.Draw();
}
}
4.6 测试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>
测试结果:
Picture.js:8 Picture Draw
Line.js:8 Line Draw
Rectangle.js:8 Rectangle Draw
Text.js:8 Text Draw
Picture.js:8 Picture Draw
Line.js:8 Line Draw
Text.js:8 Text Draw
五、源代码下载
下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw
提取码:q2ut