步步为营 .NET 设计模式学习笔记 十五、Composite(组合模式)
spring yang
概述
组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
描述Composite模式的最佳方式莫过于树形图。从抽象类或接口为根节点开始,然后生枝发芽,以形成树枝节点和叶结点。因此,Composite模式通常用来描述部分与整体之间的关系,而通过根节点对该结构的抽象,使得客户端可以将单元素节点与复合元素节点作为相同的对象来看待。
意图
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合对象的使用具有一致性。[GOF 《设计模式》]
结构图
1.安全式的合成模式的结构
安全式的合成模式要求管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件中。
这种形式涉及到三个角色:
- 抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。在安全式的合成模式里,构件角色并不是定义出管理子对象的方法,这一定义由树枝构件对象给出。
- 树叶构件(Leaf)角色:树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。
- 树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝对象给出所有的管理子对象的方法,如add()、remove()、getChild()等。
2.透明式的合成模式结构
与安全式的合成模式不同的是,透明式的合成模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定的接口。
这种形式涉及到三个角色:
- 抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象规定一个接口,规范共有的接口及默认行为。
- 树叶构件(Leaf)角色:代表参加组合的树叶对象,定义出参加组合的原始对象的行为。树叶类会给出add()、remove()以及getChild()之类的用来管理子类对对象的方法的平庸实现。
- 树枝构件(Composite)角色:代表参加组合的有子对象的对象,定义出这样的对象的行为。
生活中的例子
组合模式将对象组合成树形结构以表示"部分-整体"的层次结构。让用户一致地使用单个对象和组合对象。虽然例子抽象一些,但是算术表达式确实是组合的例子。算术表达式包括操作数、操作符和另一个操作数。操作数可以是数字,也可以是另一个表达式。这样,2+3和(2+3)+(4*6)都是合法的表达式。
图2 使用算术表达式例子的Composite模式对象图
示例用例图
建造房子正是一种组合模式,先把房子的结构建起来,再装上窗户和门就是一所房子了.来看用例图:
代码设计
先创建接口IBuild.cs:
public inte易做图ce IBuild { string Action { get; set; } string Create(); string Finish(); }
再创建Build.cs:
public abstract class Build : IBuild { private string _Action; public string Action { get { return _Action; } set { _Action = value; } } public Build(string action) { this.Action = action; } public abstract string Create(); public abstract string Finish(); }
再创建House.cs:
public class House : Build { protected List<IBuild> houseBuild = new List<IBuild>(); public House(string action) : base(action) { } public override string Create() { StringBuilder strBuilder = new StringBuilder(); strBuilder.AppendFormat("开始建造{0}. ",Action); foreach (IBuild build in houseBuild) { strBuilder.AppendLine(build.Create()); strBuilder.AppendLine(build.Finish()); } return strBuilder.ToString(); } public void Add(IBuild build) { houseBuild.Add(build); } public void Remove(IBuild build) { houseBuild.Remove(build); } public override string Finish() { return string.Format("{0}建造完成.", Action); } }
再创建Construct.cs:
public class Construct : Build { public Construct(string Action) : base(Action) { } public override string Create() { return string.Format("正在建造{0}", Action); } public override string Finish() { return string.Format("{0}建造完成.", Action); } }
再创建Window.cs:
public class Window : Build { public Window(string Action) : base(Action) { } public override string Create() { return string.Format("正在安装{0}.", Action); } public override string Finish() { return string.Format("{0}建造完成.", Action); } }
再创建Door.cs:
public class Door : Build { public Door(string Action) : base(Action) { } public override string Create() { return string.Format("正在安装{0}", Action); } public override string Finish() { return string.Format("{0}建造完成.", Action); } }
最后调用:
public partial class Run : Form
{
public Run()
{
InitializeComponent();
}
private void btnRun_Click(object sender, EventArgs e)
{
//-------------------------------------
House buildhouse = new House("房子");
buildhouse.Add(new Construct("房子结构"));
buildhouse.Add(new Window("窗户"));
buildh补充:Web开发 , ASP.Net ,