组合模式
一、定义
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得对单个对象和组合对象的使用具有一致性。
二、应用实例
文件系统中的文件与文件夹、Winform中的简单控件与容器控件、XML中的Node和Element等。
透明模式
透明模式是把组合使用的方法放到抽象类中,使得叶子对象和枝干对象具有相同的结构,客户端调用时具备完全一致的行为接口。但因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的,违背了单一职责原则和里氏替换原则。
安全模式
安全模式是把枝干和叶子节点区分开来,枝干单独拥有用来组合的方法,这种方法比较安全。但枝干和叶子节点不具有相同的接口,客户端的调用需要做相应的判断,违背了依赖倒置原则。
三、优缺点
优点
- 客户端调用简单,可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
- 可以方便的在结构中增加或者移除对象。
缺点
- 客户端需要花更多时间理清类之间的层次关系
四、示例
下面代码是用透明模式实现的
1.Component.cs
public abstract class Component { public string Name { get; set; } public Component(string name) { this.Name = name; } public abstract int SumArticleCount();
public abstract void Add(Component component);
public abstract void Remove(Component component); public abstract void Display(int depth); }
2.Composite.cs
public class Composite : Component { private List<Component> _components = new List<Component>(); public Composite(string name):base(name) { }
public override void Add(Component component) { _components.Add(component); } public override void Remove(Component component) { _components.Remove(component); } public override void Display(int depth) { Console.WriteLine(new string('-', depth) + Name); foreach (Component component in _components) { component.Display(depth + 1); } } public override int SumArticleCount() { int count = 0; foreach (var item in _components) { count += item.SumArticleCount(); } return count; } }
3.Leaf.cs
public class Leaf : Component { public Leaf(string name) : base(name) { } public override void Add(Component component) { throw new InvalidOperationException("叶子节点不能添加元素"); } public override void Remove(Component component) { throw new InvalidOperationException("叶子节点不能删除元素"); } public override int SumArticleCount() { return 1; } public override void Display(int depth) { Console.WriteLine(new string('-', depth) + Name); } }
4.Program.cs
internal class Program { static void Main(string[] args) { Component root = new Composite("目录"); Component music = new Composite("音乐"); Component knowledge = new Composite("知识"); Component life = new Composite("生活"); root.Add(music); root.Add(knowledge); root.Add(life); Component science = new Composite("科学科普"); Component tech = new Composite("野生技术协会"); knowledge.Add(science); knowledge.Add(tech); Component scienceArticle1 = new Leaf("科学科普文章1"); Component scienceArticle2 = new Leaf("科学科普文章2"); science.Add(scienceArticle1); science.Add(scienceArticle2); Component shoot = new Composite("摄影"); Component program = new Composite("编程"); Component english = new Composite("英语"); tech.Add(shoot); tech.Add(program); tech.Add(english); Component shootArticle1 = new Leaf("摄影文章1"); Component lifeArticle1 = new Leaf("生活文章1"); Component lifeArticle2 = new Leaf("生活文章2"); shoot.Add(shootArticle1); life.Add(lifeArticle1); life.Add(lifeArticle2); root.Display(0); Console.WriteLine("文章数:" + root.SumArticleCount()); } }
运行结果: