学习一些东西,我总感觉不整理一下笔记,总是感觉在脑海里没有记忆,我喜欢在学习完一定时间内,整理一下自己的
笔记,我感觉这是一笔很大的财富.
今天我就贴贴我的设计模式---组合模式的笔记!
我们先来看一下在我们使用电脑中常用到的一些组合关系,不知道大家平时注意了没有!
第一组,打开电脑,左侧栏的显示:
2,OneNote右侧的页,父页与子页
学习总是会想到生活中的一些常用的事物,学习离不开生活,在我们的生活中,还有很多地方用到组合模式,比如说公
司与子公司,提高班的公司制度等,
这些都是在生活中的组合模式,我们来认识一下官方的组合模式.
组合模式(Composite),将对象组合成树形结构以表示'部分--整体'的层次结构.组合模式使得用户对单个对
象的使用具有一致性.
要点:
1.组合模式以不遵守单一责任原则换取透明性,让Client将组合和叶节点一视同仁.
2.在实现组合 模式时,有哦获得设计上的折衷,要根据需求平衡透明性和安全性.
3.有时候系统需要遍历一个树枝构件的子构件很多次,这时候可以把遍历结构缓存起来,
4.组合模式的实现中,可以让子对象持有父对象的引用进行反向追溯
类图:
Component(抽象构建角色):是组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为,声明一个接口用
于访问和管理Component的子部件.这个接口可以用来管理所有的子对象.
Leaf(树叶结构):在组合中表示叶节点对象,叶节点没有子节点.并在组合中定义图元对象的行为.
Composite(树枝结构):定义有子部件的那些部件的行为,存储子部件.在Component接口中实现与子部件有关的操作.
Client(客户端):通过compnonent接口操纵组合部件的对象.
实现代码:
namespace 组合模式
{
/// <summary>
/// Component为组合中的对象声明接口,在适当情况下,是吸纳素有类共有接口的默认行为.
/// </summary>
/// 声明一个接口用于访问Component的子部件
///
abstract class Compnonent
{
protected string name;
public Compnonent (string name)
{
this.name = name;
}
public abstract void Add(Compnonent c);
public abstract void Remove(Compnonent c);
public abstract void Display(int depth);
}
/// <summary>
/// Leaf类,表示叶节点对象,叶节点没有子节点.
/// </summary>
///
class Leaf : Compnonent
{
public Leaf(string name)
: base(name)
{
}
public override void Add(Compnonent c)
{
Console.WriteLine("Cannot add to a leaf");
}
public override void Remove(Compnonent c)
{
Console.WriteLine("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
}
/// <summary>
/// Composite定义有枝节点行为,用存储子部件.
/// </summary>
///
class COmposite : Compnonent
{
private List<Compnonent> children = new List<Compnonent>();
public COmposite(string name)
: base(name)
{
}
public override void Add(Compnonent c)
{
children.Add(c);
}
public override void Remove(Compnonent c)
{
children.Remove(c);
}
public override void Display(int depth)
{
Console.WriteLine(new string('-', depth) + name);
foreach( Compnonent component in children )
{
component .Display (depth+2);
}
}
}
class Program
{
static void Main(string[] args)
{
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 );
COmposite comp1 = new COmposite("Composite XY");
comp1.Add(new Leaf("Leaf XYA"));
comp1.Add(new Leaf("Leaf XYB"));
comp.Add(comp1);
root .Add (new Leaf ("leaf C"));
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root.Display(1);
Console.Read();
}
}
}
结果:
优点:
1.组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个
层次结构进行控制.
2.客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端
代码.
3.在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符号"开放-封闭原则".
4.组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复
杂的树形结构,但对树形结构的控制却非常简单.
缺点:
1.使用组合模式后,控制树枝构件的类型不太容易.,有时候我们希望一个容器中只能有某些特定类型的对象.使用组合模
式时,不能依赖类型系统来施加约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来
实现,这个过程比较复杂.
2.用继承的方法来增加新的行为很困难.
使用组合模式的情况:
1.在具体整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们.
2.在一个使用面向对象语言开发的系统中需要处理一个树形结构.
3.在一个系统中能够分理出叶子对象和容器对象,而且它们的类型不固定需要增加一些新的类型.