最近比较忙,有段时间没有更新设计模式的进度了。今天继续学习组合设计模式。

  组合模式的例子我们继续延续上篇《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设计模式——组合模式的更多相关文章

  1. 16. 星际争霸之php设计模式--组合模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  2. Java设计模式——组合模式

    JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...

  3. 【设计模式】Java设计模式 - 组合模式

    Java设计模式 - 组合模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  4. c#设计模式-组合模式

    在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象和复合对象 ...

  5. [Head First设计模式]生活中学设计模式——组合模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  6. JAVA 设计模式 组合模式

    用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模式. 结构

  7. javascript设计模式-组合模式

    组合模式所要解决的问题: 可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象.可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象. 客户端代码必须区别对象简单对象和 ...

  8. 设计模式组合模式(Composite)精华

    23种子GOF设计模式一般分为三类:创建模式.结构模型.行为模式. 创建模式抽象的实例,他们帮助如何创建一个系统独立.这是一个这些对象和陈述的组合. 创建使用继承类的类架构更改实例.的对象类型模型的建 ...

  9. 设计模式 -- 组合模式 (Composite Pattern)

    定义: 对象组合成部分整体结构,单个对象和组合对象具有一致性. 看了下大概结构就是集团总公司和子公司那种层级结构. 角色介绍: Component :抽象根节点:其实相当去总公司,抽象子类共有的方法: ...

  10. javascript设计模式——组合模式

    前面的话 在程序设计中,有一些和“事物是由相似的子事物构成”类似的思想.组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更小的“孙对象”构成的.本文将详细介绍组合模式 宏命令 宏 ...

随机推荐

  1. 洛谷P3366 【模板】最小生成树(kuskal)

    #include<bits/stdc++.h> using namespace std; ; ; struct node{ int cnt,fa; }f[maxn]; inline voi ...

  2. SDUT-3334_数据结构实验之栈与队列七:出栈序列判定

    数据结构实验之栈与队列七:出栈序列判定 Time Limit: 30 ms Memory Limit: 1000 KiB Problem Description 给一个初始的入栈序列,其次序即为元素的 ...

  3. github下载慢,轻松提速教程

    获取github的IP地址访问:https://www.ipaddress.com/ 网址 依次获取以下三个网址的IP github.comgithub.global.ssl.fastly.netco ...

  4. Linux环境下第一次提交项目

    Linux环境下第一次提交项目: vi 日记 新增一个文件名为“日记”的文件 git status 工作区的状态 git add 日记 建立跟踪 git commit 提交变更 ----------- ...

  5. MVC插件式开发平台

    ---恢复内容开始--- 经过DyOS.BraveOS1.0再到BraveOS2.0,系统现在已经开发了下载. 我们的目标是,网页版操作系统,可以在线安装更新软件,并提供二次开发平台,提供基础的逻辑和 ...

  6. Java如何计算hashcode值

    在设计一个类的时候,很可能需要重写类的hashCode()方法,此外,在集合HashSet的使用上,我们也需要重写hashCode方法来判断集合元素是否相等. 下面给出重写hashCode()方法的基 ...

  7. CSP-J真题分析之中央处理器(CPU)

    中央处理器(CPU,central processing unit)作为计算机系统的运算和控制核心,是信息处理.程序运行的最终执行单元.CPU 自产生以来,在逻辑结构.运行效率以及功能外延上取得了巨大 ...

  8. 在linux上安装pear

    在搭建centreon的过程中,需要pear模块支持. 什么是pear pear是PHP扩展与应用库(the PHP Extension and Application Repository)的缩写. ...

  9. Python--day24--继承

    A_son.__bases__查看继承的父类是哪些 A. object是所有类的祖宗,所有的类都默认继承了object类. python中可以多继承 继承与抽象,先抽象再继承: example:

  10. java 创建线程方式

    1.继承Thread类 子类覆写父类中的run方法,将线程运行的代码存放在run中. 建立子类对象的同时线程也被创建. 通过调用start方法开启线程. 2.实现Runnable接口 子类覆盖接口中的 ...