js组合模式
组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
- 透明方式,也就是说在Commponent中声明所有用来管理子对象的方法,其中包括Add、Remove等。这样实现Commponent接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的。
- 安全方式,也就是在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。
透明式的组合模式类图:

安全式组合模式的类图:

组合模式中涉及到三个角色:
- 抽象构件(Component)角色:这是一个抽象角色,上面实现中Graphics充当这个角色,它给参加组合的对象定义出了公共的接口及默认行为,可以用来管理所有的子对象(在透明式的组合模式是这样的)。在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝结构对象给出。
- 树叶构件(Leaf)角色:树叶对象时没有下级子对象的对象,上面实现中Line和Circle充当这个角色,定义出参加组合的原始对象的行为
- 树枝构件(Composite)角色:代表参加组合的有下级子对象的对象,上面实现中ComplexGraphics充当这个角色,树枝对象给出所有管理子对象的方法实现,如Add、Remove等。
组合模式的使用场景
在以下情况下应该考虑使用组合模式:
- 需要表示一个对象整体或部分的层次结构。
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
C#组合模式:
namespace 组合模式
{
class Program
{
static void Main(string[] args)
{
ConcreteCompany root = new ConcreteCompany("北京总公司");
root.Add(new HRDepartment("总公司人力资源部"));
root.Add(new FinanceDepartment("总公司财务部")); ConcreteCompany comp = new ConcreteCompany("上海华东分公司");
comp.Add(new HRDepartment("华东分公司人力资源部"));
comp.Add(new FinanceDepartment("华东分公司财务部"));
root.Add(comp); ConcreteCompany comp1 = new ConcreteCompany("南京办事处");
comp1.Add(new HRDepartment("南京办事处人力资源部"));
comp1.Add(new FinanceDepartment("南京办事处财务部"));
comp.Add(comp1); ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");
comp2.Add(new HRDepartment("杭州办事处人力资源部"));
comp2.Add(new FinanceDepartment("杭州办事处财务部"));
comp.Add(comp2); Console.WriteLine("\n结构图:"); root.Display(1); Console.WriteLine("\n职责:"); root.LineOfDuty(); Console.Read();
}
} abstract class Company
{
protected string name; public Company(string name)
{
this.name = name;
} public abstract void Add(Company c);//增加
public abstract void Remove(Company c);//移除
public abstract void Display(int depth);//显示
public abstract void LineOfDuty();//履行职责 } class ConcreteCompany : Company
{
private List<Company> children = new List<Company>(); public ConcreteCompany(string name)
: base(name)
{ } public override void Add(Company c)
{
children.Add(c);
} public override void Remove(Company c)
{
children.Remove(c);
} public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name); foreach (Company component in children)
{
component.Display(depth + 2);
}
} //履行职责
public override void LineOfDuty()
{
foreach (Company component in children)
{
component.LineOfDuty();
}
} } //人力资源部
class HRDepartment : Company
{
public HRDepartment(string name)
: base(name)
{ } public override void Add(Company c)
{
} public override void Remove(Company c)
{
} public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
} public override void LineOfDuty()
{
Console.WriteLine("{0} 员工招聘培训管理", name);
}
} //财务部
class FinanceDepartment : Company
{
public FinanceDepartment(string name)
: base(name)
{ } public override void Add(Company c)
{
} public override void Remove(Company c)
{
} public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
} public override void LineOfDuty()
{
Console.WriteLine("{0} 公司财务收支管理", name);
} }
}
js组合模式:
<html>
<body>
<button id="button">按我</button>
</body>
<script>
var MacroCommand = function(){
return{
commandsList:[],
add:function(command){
this.commandsList.push(command);
},
execute:function(){
for(var i=0,command;command=this.commandsList[i++];){
command.execute();
}
}
}
}; var openAcCommand = {
execute:function(){
console.log('打开空调');
}
}; /*****************家里的电视和音响是连接在一起的,所以可以用一个宏命令来组合打开电视和打开音响的命令********************/ var openTvCommand = {
execute:function(){
console.log('打开电视');
}
}; var openSoundCommand = {
execute:function(){
console.log('打开音响');
}
}; var macroCommand1 = MacroCommand();
macroCommand1.add(openTvCommand);
macroCommand1.add(openSoundCommand); /***********关门、打开电脑和登录QQ的命令**************/ var closeDoorCommand = {
execute:function(){
console.log('关门');
}
}; var openPcCommand = {
execute:function(){
console.log('开电脑');
}
}; var openQQCommand = {
execute:function(){
console.log('登录QQ');
}
}; var macroCommand2 = MacroCommand();
macroCommand2.add(closeDoorCommand);
macroCommand2.add(openPcCommand);
macroCommand2.add(openQQCommand); /******************现在把所有的命令组合成一个“超级命令”*********************/ var macroCommand = MacroCommand();
macroCommand.add(openAcCommand);
macroCommand.add(macroCommand1);
macroCommand.add(macroCommand2); /**************最后给遥控器绑定“超级命令”**********************/ var setCommand = (function(command){
document.getElementById('button').onclick = function(){
command.execute();
}
})(macroCommand); </script>
</html>
javascript中实现组合模式的难点在于要保证组合对象和叶对象对象拥有同样的方法,这通常需要用鸭子类型的思想对它们进行接口检查。
组合对象可以拥有子节点,叶对象下面就没有子节点,所以我们也许会发生一些误操作,比如试图往叶对象中添加子节点,解决方案通常是给叶对象叶增加add方法,并且在调用这个方法时,抛出一个异常来及时提醒客户,代码如下:
var MacroCommand = function(){
return{
commandsList:[],
add:function(command){
this.commandsList.push(command);
},
execute:function(){
for(var i=0,command;command=this.commandsList[i++];){
command.execute();
}
}
}
};
var openTvCommand = {
execute:function(){
console.log('打开电视');
},
add:function(){
throw new Error('叶对象不能添加子节点');
}
};
var macroCommand = MacroCommand();
macroCommand.add(openTvCommand);
openTvCommand.add(macroCommand); //Uncaugth Error:叶对象不能添加子节点
js组合模式的更多相关文章
- javascript设计模式(张容铭) 第14章 超值午餐-组合模式 学习笔记
JS 组合模式更常用于创建表单上,比如注册页面可能有不同的表单提交模块.对于这些需求我们只需要有基本的个体,然后通过一定的组合即可实现,比如下面这个页面样式(如图14-2所示),我们来用组合模式实现. ...
- js架构设计模式——你对MVC、MVP、MVVM 三种组合模式分别有什么样的理解?
你对MVC.MVP.MVVM 三种组合模式分别有什么样的理解? MVC(Model-View-Controller)MVP(Model-View-Presenter)MVVM(Model-View-V ...
- [js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表
所谓组合模式,就是把一堆结构分解出来,组成在一起,现实中很多这样的例子,如: 1.肯德基套餐就是一种组合模式, 比如鸡腿堡套餐,一般是是由一个鸡腿堡,一包薯条,一杯可乐等组成的 2.组装的台式机同理, ...
- js设计模式(六)---组合模式
组合模式将对象组合成树形结构,以表示“部分-整体”的层次结构.除了用来表示树形结构之外,组合模式的另一个好处是通过对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性.基本图例 1.组合模式 ...
- JS设计模式(7)组合模式
什么是组合模式? 定义:1.将对象组合成树形结构以表示"部分-整体"的层次结构.2.组合模式使得用户对单个对象和组合对象的使用具有一致性.3.无须关心对象有多少层,调用时只需在根部 ...
- js设计模式-组合模式
组合模式是一种专为创建web上的动态用户界面而量身定制的模式.使用这种模式,可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更容易维护,而那些复杂行为则被委托给各个对象. ...
- JS常用的设计模式(13)——组合模式
组合模式又叫部分-整体模式,它将所有对象组合成树形结构.使得用户只需要操作最上层的接口,就可以对所有成员做相同的操作. 一个再好不过的例子就是jquery对象,大家都知道1个jquery对象其实是一组 ...
- js设计模式(4)---组合模式
0.前言 今天是建党节,新疆那边又开始了闹腾.作为立志成为码农的我,现在已经从一个大愤青淡化为一个小愤青,对这些国家民生大事不在血气喷发,转而把经历发泄在技术问题上面,因而在扯一篇随笔吧,把无处发泄的 ...
- JS设计模式——9.组合模式
组合模式概述 组合模式是一种专为创建Web上的动态用户界面量身定制的模式.使用这种模式可以用一条命令在多个对象上激发复杂的递归的行为. 它可以用来把一批子对象组织成树形结构,并且使整棵树都可被遍历.所 ...
随机推荐
- MVC5学习系列
前言 嗷~小弟我又出现了~咳咳..嚎过头了, 先说一说为什么写这个吧,~首先肯定是我自己需要学(废话 - -,)//,之前也写过MVC4的项目,嗯..但是仅限于使用并没有很深入的每个模块去了解, 这段 ...
- 控制bin文件夹里面的dll不复制到临时目录中( <hostingEnvironment shadowCopyBinAssemblies="false" />)
One of the things that makes developing ASP.NET applications very cool is that you can rapidly proto ...
- MFC重绘原理的关键理解
// ====================Windows重绘消息与函数========================== 得到桌面窗口的句柄,然后再绘图HWND GetDesktopWindow ...
- diff工具
Beyond Compare 4 可以diff文件夹.单个文件.
- DMR技术白皮书
DMR技术白皮书 主页(http://pttcn.net):DMR技术白皮书 关于DMR 1.模拟技术的局限性 虽然模拟技术仍具有不少优势,如低廉的成本.可自定的功能以及简便的搭建方式等.但模拟技术已 ...
- boost之正则表达式
正则表示主要用于查找一系列符合规则的对象,而我们之前的查找是对某一特定的字符串进行查找. #include <iostream> #include <vector> #incl ...
- Python之异常处理(Day27)
一.错误和异常 part1: 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 def test: pass #语法错 ...
- Django_Form表单补充
Form表单 问题1: 注册页面输入为空,报错:keyError:找不到password def clean(self): print("---",self.cleaned_da ...
- 运维角度浅谈MySQL数据库优化
一个成熟的数据库架构并不是一开始设计就具备高可用.高伸缩等特性的,它是随着用户量的增加,基础架构才逐渐完善.这篇博文主要谈MySQL数据库发展周期中所面临的问题及优化方案,暂且抛开前端应用不说,大致分 ...
- 基于IG的特征评分方法
本文简单介绍了熵.信息增益的概念,以及如何使用信息增益对监督学习的训练样本进行评估,评估每个字段的信息量. 1.熵的介绍 在信息论里面,熵是对不确定性的测量.通俗来讲,熵就是衡量随机变量随 ...