Head First设计模式——组合模式
最近比较忙,有段时间没有更新设计模式的进度了。今天继续学习组合设计模式。
组合模式的例子我们继续延续上篇《Head First设计模式——迭代器模式》的菜单例子,首先声明下迭代器和组合模式没有什么关系,他们是两个不同模式。只是我们在这个菜单例子的组合模式内部会用到迭代器。
迭代器模式中说到两个餐馆合并然后使用迭代器进行统一处理菜单的打印,但是现在有一个新的需求是原来大菜单中我们希望加入子菜单,比如饭后甜点。那么这个时候对于需求模型来说就是类似下面这样

菜单拥有菜单项,菜单项中可能还拥有子菜单,我们现在要打印菜单。也就是处理每个菜单和菜单项,如何将他们合理的组织起来并统一处理?要解决这个问题,组合模式来实现这一需求。
定义组合模式
组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
这个模式能够创建一个树形结构,如果我们有了一个树形结构的菜单、子菜单和可能还带有菜单项的子菜单,那么任何一个菜单都是一种“组合”。因为它既可以包含其他菜单,也可以包含菜单项。个别对象只是菜单项并未持有其他对象。
利用组合设计菜单
我们需要创建一个组件接口来作为菜单和菜单项的共同接口,让我们能够用统一的做法来处理菜单和菜单项,换句话说,我们可以针对菜单或菜单项调用相同的方法。
我们画出菜单设计的类图:

MenuComponent:提供接口,让菜单项和菜单共同使用。我们可能会对方法提供一些默认实现,所以我们可以使用抽象类。
MenuItem:继承自MenuComponent,覆盖了它有意义的方法(add,remove不用管)。
Menu:继承自MenuComponent,覆盖对它有意义的方法。
实现组合模式
实现菜单组件
public abstract class MenuComponent
{
public virtual void Add(MenuComponent menuComponent) {
throw new NotSupportedException();
}
public virtual void Remove(MenuComponent menuComponent)
{
throw new NotSupportedException();
}
public virtual MenuComponent GetChild(int i)
{
throw new NotSupportedException();
}
public virtual void GetName()
{
throw new NotSupportedException();
}
public virtual string GetDescription()
{
throw new NotSupportedException();
}
public virtual double GetPrice()
{
throw new NotSupportedException();
}
public virtual bool IsVegetarian()
{
throw new NotSupportedException();
}
public virtual void Print()
{
throw new NotSupportedException();
}
}
实现菜单项
public class MenuItme : MenuComponent
{
string name;
string decription;
bool vegetarian;
double price; public MenuItme(string name, string decription, bool vegetarian, double price)
{
this.name = name;
this.decription = decription;
this.vegetarian = vegetarian;
this.price = price;
} public override string GetName()
{
return name;
}
public override string GetDescription()
{
return decription;
}
public override double GetPrice()
{
return price;
}
public override bool IsVegetarian()
{
return vegetarian;
}
public override void Print()
{
Console.Write(" " + GetName());
if (IsVegetarian())
{
Console.Write("V" + GetName());
}
Console.WriteLine("," + GetPrice());
Console.WriteLine(" --" + GetPrice());
}
}
实现组合菜单
public class Menu:MenuComponent
{
List<MenuComponent> menuComponents = new List<MenuComponent>();
string name;
string description;
public Menu(string name, string description)
{
this.name = name;
this.description = description;
}
public override void Add(MenuComponent menuComponent)
{
menuComponents.Add(menuComponent);
}
public override void Remove(MenuComponent menuComponent)
{
menuComponents.Remove(menuComponent);
}
public override MenuComponent GetChild(int i)
{
return menuComponents[i];
}
public override string GetName()
{
return name;
}
public override string GetDescription()
{
return description;
} public override void Print()
{
Console.Write("\n" + GetName());
Console.WriteLine("," + GetDescription());
Console.WriteLine("---------------------");
foreach (var item in menuComponents)
{
item.Print();
}
}
}
这里菜单打印直接用foreach 循环打印菜单组件,如果遇到另外一个菜单对象则进入子菜单打印。此处就是使用迭代器模式,只不过我偷了个懒直接用了foreach,因为list C#已经实现了迭代器,使用foreach语法即可。《C# Foreach循环本质与枚举器》
测试
MenuComponent breakfastMenu = new Menu("早餐菜单", "早餐供应");
MenuComponent dinnerMenu = new Menu("晚餐菜单", "晚餐供应");
MenuComponent dessertMenu = new Menu("甜点菜单", "晚餐甜点");
MenuComponent allMenus = new Menu("ALL MENUS", "all menus combaind");
//加入菜单
allMenus.Add(breakfastMenu);
allMenus.Add(dinnerMenu);
//加入菜单项
breakfastMenu.Add(new MenuItme("包子", "鲜肉酱肉", false, 2));
dinnerMenu.Add(new MenuItme("牛肉拉面", "拉面配牛肉", false, 15));
dinnerMenu.Add(dessertMenu);
dessertMenu.Add(new MenuItme("梦龙卷", "切件", false, 16));
allMenus.Print();

Head First设计模式——组合模式的更多相关文章
- 16. 星际争霸之php设计模式--组合模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- Java设计模式——组合模式
JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...
- 【设计模式】Java设计模式 - 组合模式
Java设计模式 - 组合模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...
- c#设计模式-组合模式
在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象和复合对象 ...
- [Head First设计模式]生活中学设计模式——组合模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
- JAVA 设计模式 组合模式
用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模式. 结构
- javascript设计模式-组合模式
组合模式所要解决的问题: 可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象.可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象. 客户端代码必须区别对象简单对象和 ...
- 设计模式组合模式(Composite)精华
23种子GOF设计模式一般分为三类:创建模式.结构模型.行为模式. 创建模式抽象的实例,他们帮助如何创建一个系统独立.这是一个这些对象和陈述的组合. 创建使用继承类的类架构更改实例.的对象类型模型的建 ...
- 设计模式 -- 组合模式 (Composite Pattern)
定义: 对象组合成部分整体结构,单个对象和组合对象具有一致性. 看了下大概结构就是集团总公司和子公司那种层级结构. 角色介绍: Component :抽象根节点:其实相当去总公司,抽象子类共有的方法: ...
- javascript设计模式——组合模式
前面的话 在程序设计中,有一些和“事物是由相似的子事物构成”类似的思想.组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更小的“孙对象”构成的.本文将详细介绍组合模式 宏命令 宏 ...
随机推荐
- Datanodes-心跳机制
- Android的headerView和emptyView共存问题
今天做项目的时候,准备优化下ListView相关的东西,于是乎,需要做一个当列表无数据时,空的提醒页面.这个自然想到的是ListView的setEmptyView()方法,于是顺手就写了,可是,当我为 ...
- Linux 运算符
布尔运算符 下表列出了常用的布尔运算符,假定变量a为10 变量b为20: 运算符 说明 举例 ! 非运算 , 表达式为true 则返回false 否则返回true [!false] 返回true. ...
- H3C 路由器的特点
- oracle 优化GROUP BY
提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多. 低效: SELECT JOB , AVG(SAL) FROM ...
- oracle强制索引失效
如果两个或以上索引具有相同的等级,你可以强制命令ORACLE优化器使用其中的一个(通过它,检索出的记录数量少) . 举例: SELECT ENAME FROM EMP WHERE EMPNO = 79 ...
- Object类型的创建和访问
创建Object实例的方式有两种: 1.使用new操作符后跟object构造函数 var person=new Object(); person.name='Nicholas'; person.age ...
- Codeforces Round #168 (Div. 1 + Div. 2)
A. Lights Out 模拟. B. Convex Shape 考虑每个黑色格子作为起点,拐弯次数为0的格子构成十字形,拐弯1次的则是从这些格子出发直走达到的点,显然需要遍历到所有黑色黑色格子. ...
- 最全Pycharm教程(43)——Pycharm扩展功能之UML类图使用 代码结构
版权声明:本文为博主原创文章,转载时麻烦注明源文章链接,谢谢合作 https://blog.csdn.net/u013088062/article/details/50353202 1.什么是UML ...
- Appium + python 自动化测试环境配置
-------------------------------------------------------------- 1. jdk-8u121-window(32位的就下载32位的,64位的就 ...