1、組合模式簡介
1.1>、定義
組合模式主要用來處理一類具有“容器特徵”的物件——即它們在充當物件的同時,又可以作為容器包含其他多個物件。
1.2>、使用頻率
中高
2、組合模式結構圖
2.1>、結構圖
2.2>、參與者
組合模式參與者:
◊ Component
° 宣告組合中物件的介面;
° 實現全部類中公共介面的預設行為;
° 宣告訪問和管理子類的介面;
° (可選擇)定義介面提供在遞迴結構中訪問父類。
◊ Leaf
° 表示在組合物件中葉子節點物件,沒有子節點;
° 定義組合物件中的初始行為。
◊ Composite
° 定義Component子類的行為;
° 儲存Component子類;
° 實現Component介面的子類關聯操作。
◊ Client
° 通過Component介面組合多個物件。
3、組合模式結構實現
Component.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Structural { public abstract class Component { protected string _name; public Component(string name) { this._name = name; } public abstract void Add(Component c); public abstract void Remove(Component c); public abstract void Display(int depth); } }
Leaf.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Structural { public class Leaf : Component { public Leaf(string name) : base(name) { } public override void Add(Component c) { Console.WriteLine("Cannot add to a leaf"); } public override void Remove(Component c) { Console.WriteLine("Cannot remove from a leaf"); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + _name); } } }
Composite.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Structural { public class Composite : Component { private List<Component> _children = new List<Component>(); public Composite(string name) : base(name) { } public override void Add(Component component) { _children.Add(component); } public override void Remove(Component component) { _children.Remove(component); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + _name); foreach (Component component in _children) { component.Display(depth + 2); } } } }
Client.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Structural { public class Client { static void Main(string[] args) { // Create a tree structure Composite root = new Composite("root"); root.Add(new Leaf("Leaf A")); root.Add(new Leaf("Leaf B")); Composite comp = new Composite("Composite X"); comp.Add(new Leaf("Leaf XA")); comp.Add(new Leaf("Leaf XB")); root.Add(comp); root.Add(new Leaf("Leaf C")); // Add and remove a leaf Leaf leaf = new Leaf("Leaf D"); root.Add(leaf); root.Remove(leaf); // Recursively display tree root.Display(1); } } }
執行結果:
-root ---Leaf A ---Leaf B ---Composite X -----Leaf XA -----Leaf XB ---Leaf C 請按任意鍵繼續. . .
4、組合模式實踐應用
Shape.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Practical { public abstract class Shape { protected string _name; public Shape(string name) { this._name = name; } /// <summary> /// 面積 /// </summary> /// <returns></returns> public abstract double Area(); /// <summary> /// 顯示 /// </summary> public abstract void Display(); } }
Circle.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Practical { /// <summary> /// 圓形 /// </summary> public class Circle : Shape { private double _radius; public Circle(string name, double radius) : base(name) { this._radius = radius; } public override double Area() { return Math.Round(Math.PI * _radius * _radius, 2); } public override void Display() { Console.WriteLine("{0} 半徑:{1},面積:{2}", _name, _radius, this.Area()); } } }
Rectangle.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Practical { /// <summary> /// 矩形 /// </summary> public class Rectangle : Shape { private double _width; private double _height; public Rectangle(string name, double width, double height) : base(name) { this._width = width; this._height = height; } public override double Area() { return _width * _height; } public override void Display() { Console.WriteLine("{0} 長:{1},寬:{2},面積:{3}", _name, _width, _height, this.Area()); } } }
Triangle.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Practical { /// <summary> /// 三角形 /// </summary> public class Triangle : Shape { private double _a; private double _b; private double _c; /// <summary> /// 三角形建構函式 /// 引數:三角形名稱和三條邊長 /// </summary> /// <param name="name">三角形名稱</param> /// <param name="a">第一條邊長</param> /// <param name="b">第二條邊長</param> /// <param name="c">第三條邊長</param> public Triangle(string name, double a, double b, double c) : base(name) { _a = a; _b = b; _c = c; } public override double Area() { double p = (_a + _b + _c) / 2; return Math.Sqrt(p * (p - _a) * (p - _b) * (p - _c)); } public override void Display() { Console.WriteLine("{0} 三條邊長:{1},{2},{3},面積:{3}", _name, _a, _b, _c, this.Area()); } } }
Graphics.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Practical { public class Graphics : Shape { private List<Shape> _children = new List<Shape>(); public Graphics(string name) : base(name) { } public override double Area() { double sum = 0; foreach (Shape child in _children) { sum += child.Area(); } return sum; } public override void Display() { foreach (Shape child in _children) { child.Display(); } Console.WriteLine("{0} 總面積:{1}", _name, this.Area()); } public void Add(Shape child) { _children.Add(child); } public void Remove(Shape child) { _children.Remove(child); } } }
Client.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.CompositePattern.Practical { public class Client { static void Main(string[] args) { Graphics graphics = new Graphics("全部圖形"); Circle circle = new Circle("圓形", 5); graphics.Add(circle); Rectangle rectangle = new Rectangle("矩形", 4, 5); graphics.Add(rectangle); Triangle triangle = new Triangle("三角形", 3, 4, 5); graphics.Add(triangle); graphics.Display(); } } }
執行結果:
圓形 半徑:5,面積:78.54 矩形 長:4,寬:5,面積:20 三角形 三條邊長:3,4,5,面積:5 全部圖形 總面積:104.54 請按任意鍵繼續. . .
5、組合模式應用分析
組合模式可以適用以下情形:
◊ 希望把物件表示成部分—整體層次結構;
◊ 希望使用者忽略組合物件與單個物件的不同,使用者將統一地使用組合結構中所有物件。
組合模式具有以下特點:
◊ 定義了包含基本物件和組合物件的類層次結構。基本物件可以被組合成更復雜的組合物件,而這個組合物件又可以被組合,不斷的遞迴下去。客戶程式碼中,任何用到基本物件的地方都可以使用組合物件;
◊ 簡化客戶程式碼。客戶可以一致地使用組合結構和單個物件。這樣使用者就不必關心處理的是一個葉子節點還是一個組合元件,從而簡化了客戶程式碼;
◊ 使得新增型別的元件更加容易。新定義的Composite或Leaf子類自動地與已有的結構和客戶程式碼一起協同工作,客戶程式不需因新的Component類而改變。
6、參考資料