组合模式
2015-10-18 19:56
543 查看
组合模式大概是设计模式里面使用最为广泛的模式之一了,模式本身理解起来也比较简单,以至于可以毫不费力的写出一个能用的组合模式伪代码。
以上是传统面向对象语言对于组合模式的一个规范实现,由于Javascript这种动态语言本身的一些限制,我们通过在
输出:
输出
2.节点必须有统一的操作接口
该模式解决了什么问题?
组合模式统一对待复合对象与单个对象。抽象出统一的命令执行接口,这种多态性使得客户端在编写代码的时候可以不加区分当前要操作的是复合对象还是单个对象。
组合模式基本实现
function inherits(child, sup) { child.prototype = Object.create(sup.prototype, { constructor: { value: child, enumerable: false, configurable: true, writable: true } }); } //组合对象与叶子对象都集成自component对象 function Component() { } Component.prototype.execute = function(context) { throw new Error('Component function must be override'); }; Component.prototype.add = function(command) { throw new Error('Component function must be override'); }; Component.prototype.remove = function(command) { throw new Error('Component function must be override'); }; function Composite() { this.childs = []; Component.call(this); } inherits(Composite, Component); Composite.prototype.execute = function(context) { for(var i = 0; i < this.childs.length; i++) { this.childs[i].execute(context); } }; Composite.prototype.add = function(child) { this.childs.push(child); }; Composite.prototype.remove = function(child) { for(var i = 0; i < this.childs.length; i++) { if(child == this.childs[i]) { this.childs.splice(i, 1); } } }; //叶子节点不能添加子对象 function Leaf(command) { Component.call(this); this.command = command; } inherits(Leaf, Component); Leaf.prototype.execute = function(context) { if(!this.command) return; this.command.execute(context); };
以上是传统面向对象语言对于组合模式的一个规范实现,由于Javascript这种动态语言本身的一些限制,我们通过在
基类抛出异常的方式来阻止客户端往
Leaf对象中添加子对象,代码整体来看会有一些冗余,下面来写一个简单的实现。
Javascript下的实现
组合模式无非就是需要一个列表来存放子对象,这些对象往往是一些需要被执行的命令(常和命令模式组合运用)。所以我们可以写成如下形式:
var CompositeCommand = function() { return { commandList: [], add: function(command) { this.commandList.push(command); }, execute: function(context) { for(var i = 0, length = this.commandList.length; i < length; i++) { var command = this.commandList[i]; command.execute(context); } } }; } var openWindowCommand = { execute: function(ctx) { console.log('openWindowCommand'); } }; var playMusicCommand = { execute: function(ctx) { console.log('playMusicCommand'); } }; var closeDoorCommand = { execute: function(ctx) { console.log('closeDoorCommand'); } }; var composite1 = CompositeCommand(); composite1.add(playMusicCommand); composite1.add(openWindowCommand); var composite = CompositeCommand(); composite.add(composite1); composite.add(closeDoorCommand); composite.execute();
输出:
playMusicCommand openWindowCommand closeDoorCommand
组合模式常用的一般情况
组合模式适用于对一组对象执行同一类操作,而这组对象有可能是包含关系,也可以是单个个体。常用的情形如:文件扫描,我们扫描文件的时候并不关心当前是文件夹或者是单个文件,都可以统一执行scan接口,当然前提是我们已经得到了一组文件对象的依赖关系。再如,GUI绘制界面的时候,通常会先绘制主窗口渲染背景,然后再绘制叠加在窗口上的各个子控件,而这些子控件有可能又包含一些子控件。基于GUI控件的依赖层次关系。也非常适合使用组合模式:
var createDialog = function () { return { bgimg: 'blues.png', children: [], addChild: function(child) { this.children.push(child); }, paintSelf: function(context) { console.log('paint dialog'); }, paint: function(context) { this.paintSelf(context); for(var i = 0, length = this.children.length; i< length; i++) { var child = this.children[i]; child.paint(context); } } }; } var createButton = function() { return { paint: function(ctx) { console.log('paint button'); } }; }; var createListView = function() { return { children: [], addChild: function(item) { this.children.push(item); }, paint: function(ctx) { console.log('paint listview'); for(var i = 0; i < this.children.length; i++) { this.children[i].paint(ctx); } } }; }; var createListItem = function() { return { paint: function(ctx) { console.log('paint list item'); } }; }; var window = createDialog(); var dialog1 = createDialog(); dialog1.addChild(createButton()); window.addChild(dialog1); var dialog2 = createDialog(); var listview = createListView(); listview.addChild(createListItem()); dialog2.addChild(listview); window.addChild(dialog2); window.paint({});
输出
paint dialog paint dialog paint button paint dialog paint listview paint list item
后记
1.复合对象与单个对象不是父子关系,二是聚合(has-A)关系。2.节点必须有统一的操作接口
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- PropertyChangeListener简单理解
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 七、设计模式——装饰模式
- 设计模式总结
- 设计模式之创建型模式
- 浅谈设计模式的学习
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因
- Canvas 在高清屏下绘制图片变模糊的解决方法