-
Composite Pattern
组合模式(Composite Design Pattern)主要功能是能够使客户端(Client Code) 平等的对待单一组件(Single Componets)和容器组件(Container Componen)。从而实现客户端代码与组件之间的解耦。 -
适用场景
Composites that contain Components, each of which could be a Composite.
组合中包含组件,每个组件有可能也是一个组合。 -
解决问题
Application needs to manipulate a hierarchical collection of “primitive” and “composite” objects. Processing of a primitive object is handled one way, and processing of a composite object is handled differently. Having to query the “type” of each object before attempting to process it is not desirable. -
模式分析
从上图可以看出,Client依赖与抽象Component,该抽象可以是interface 或abstract类。Leaf和Composite泛化于Component,同时Composite依赖于Component。习惯上称像Leaf这样的Single Componet为叶子组件,Composite这样的Container Componet为树枝,Component为根(root)。该模式主要用在容器组件递归调用。 -
代码示例
ASP.Net中控件都有Render方法,控件类型有容器类型(Panel,Form)与非容器类型(Button)。下面代码模拟Form显示窗体上所有控件。
/*
* composite Pattern
* 组合模式
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Pattern01
{
class Program
{
static void Main(string[] args)
{
Form form = new Form();
Button buttonInForm = new Button();
Console.WriteLine("Container's Render Method excute.");
form.Add(buttonInForm);
form.Render();
Console.WriteLine("Single's Render Method excute.");
Button button = new Button();
button.Render();
Console.ReadKey();
}
}
/// <summary>
/// Component
/// </summary>
public interface IControl
{
void Render();
}
/// <summary>
/// Leaf
/// </summary>
public class Button : IControl
{
public void Render()
{
Console.WriteLine("Button Rended");
}
}
/// <summary>
/// Composite
/// </summary>
public class Form : IControl
{
private List<IControl> controls = new List<IControl>();
public void Add(IControl control)
{
controls.Add(control);
}
public void Remove(IControl control)
{
controls.Remove(control);
}
public void Render()
{
Console.WriteLine("Form Rended");
if (controls != null)
{
foreach (var control in controls)
{
control.Render();
}
}
}
}
}
- structural code
/*
*Composite Pattern
* 可以让client 访问类整体的结构,不管它是一个leaf node,还是一个compont
* Composites that contain Components, each of which could be a Composite.
*
* 包含组件的组合,每个组件都可以是一个组合。
*/
using System;
using System.Collections.Generic;
namespace Pattern03
{
class Program
{
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);
Console.ReadKey();
}
}
/// <summary>
/// 声明组合中对象的接口。
/// 为所有类通用的接口实现默认行为。
/// 声明用于访问和管理其子组件的接口。
/// (可选) 定义一个接口,用于在递归结构中访问组件的父组件,并在适当的情况下实现它。
/// </summary>
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);
}
/// <summary>
/// 定义具有子组件的行为
/// 存储子组件。
/// 在组件接口中实现子操作。
/// </summary>
class Composite : Component
{
private List<Component> _children = new List<Component>();
public Composite(string name) : base(name)
{
}
public override void Add(Component c)
{
_children.Add(c);
}
public override void Remove(Component c)
{
_children.Remove(c);
}
public override void Display(int depth)
{
//这里实现递归调用,如果组件是node--leaf 则直接调用其display方法,如果是组件是composite--组合,
//则调用 此处的Display--从而实现迭代。
Console.WriteLine(new string('-', depth) + name);
foreach (Component component in _children)
{
component.Display(depth + 2);//
}
}
}
/// <summary>
/// represents leaf objects in the composition. A leaf has no children.没有其他子类
/// defines behavior for primitive objects in the composition.实现composition中的方法
/// </summary>
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 Pattern