设计模式-结构型-组合模式
文章目录
组合模式
组合模式(整体-部分模式):将单个对象和组合对象用相同的接口进行表示,使客户对单个对象和组合对象的使用具有一致性。
一、组合模式是什么?
使系统内个层次对象的行为具有一致性操作。
一般用来表示整体与部分的关系,将对象组织到树形结构中,顶层的节点被称为根节点,根节点下可以包含树枝节点—>叶子节点---->细胞节点。根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用,在组合模式中上级节点和中级节点对应的中级和下级节点的数据类型时一致的,好处就是不用再区分级别,可以直接进行操作。
1.应用场景
- 树形菜单,公司组织架构,和操作系统目录结构。
- 当子系统与其内各个对象层次呈树形结构时,可以使用组合模式让子系统内各个对象层次的行为操作具备一致性,被使用时,不需要考虑层级因素,直接使用通用操作,非常敏捷。
- 当调用者可以忽略组合对象与单个对象的差异时应用组合模式。
- 对象层次具备整体和部分,呈树形结构,可以忽略层级间的差异,直接使用通用操作。
2.角色
- 组件(Component):抽象组件(接口或抽象类)描述了树中各层级项目所共有的操作。
- 页节点(Leaf):是树的基本结构, 它不包含子项目。
- 组合(Composite):是包含叶节点或其他组合子项目的单位。 不知道子项目所属的具体类, 只通过通用的组件接口与其子项目交互。
二、使用步骤
1.透明组合模式:将所有公共方法定义到Component中
好处:无须分辨叶子节点和树枝节点,他们具有完全一致的操作。
代码如下(示例):定义抽象公共操作方法类
/// <summary>
/// 抽象公共方法组件
/// </summary>
public abstract class Company_Component
{
public string name { get; set; }
public Company_Component(string name)
{
this.name = name;
}
public abstract void Operation();
public abstract void AddChild(Company_Component component);
public abstract void RemoveChild(Company_Component component);
}
代码如下(示例):定义树节点具体实现,继承Component公共操作类
/// <summary>
/// 实现枝节点
/// </summary>
public class Company_Composite : Company_Component
{
public string name { get; set; }
public List<Company_Component> company_Components;
public Company_Composite(string name) : base(name)
{
this.name = name;
this.company_Components = new List<Company_Component>();
}
public override void Operation()
{
Console.WriteLine("组合节点" + name + "的操作");
//调用所有子节点的操作
foreach (var item in company_Components)
{
item.Operation();
}
}
public override void AddChild(Company_Component component)
{
Console.WriteLine($"当前节点:{this.name}添加---{component.name}节点");
company_Components.Add(component);
}
public override void RemoveChild(Company_Component component)
{
company_Components.Remove(component);
}
}
代码如下(示例):定义叶子节点具体实现,继承Component公共操作类
/// <summary>
/// 实现叶节点
/// </summary>
public class Company_Leaf : Company_Component
{
public Company_Leaf(string name) : base(name)
{
}
public override void AddChild(Company_Component component)
{
Console.WriteLine("叶节点不能添加节点");
}
public override void Operation()
{
Console.WriteLine("叶节点" + name + "的操作");
}
public override void RemoveChild(Company_Component component)
{
Console.WriteLine("叶节点没有节点");
}
}
代码如下(示例):客户端对各类节点进行调用
/// <summary>
/// 客户端调用
/// </summary>
public void Client()
{
//创建根节点对象
Company_Component component = new Company_Composite("component");
//Console.WriteLine($"当前节点:{component.name}");
//创建两个组合节点对象
Company_Component composite1 = new Company_Composite("composite1");
Company_Component composite2 = new Company_Composite("composite2");
//将两个组合节点对象添加到根节点
component.AddChild(composite1);
component.AddChild(composite2);
//给第一个组合节点对象添加两个叶子节点
Company_Component leaf1 = new Company_Leaf("leaf1");
Company_Component leaf2 = new Company_Leaf("leaf2");
composite1.AddChild(leaf1);
composite1.AddChild(leaf2);
//给第二个组合节点对象添加一个叶子节点和一个组合节点
Company_Component leaf3 = new Company_Leaf("leaf3");
Company_Component composite3 = new Company_Composite("composite3");
composite2.AddChild(leaf3);
composite2.AddChild(composite3);
//给第二个组合节点下面的组合节点添加两个叶子节点
Company_Component leaf4 = new Company_Leaf("leaf4");
Company_Component leaf5 = new Company_Leaf("leaf5");
composite3.AddChild(leaf4);
composite3.AddChild(leaf5);
//执行所有节点的操作
// component.Operation();
}
2.安全组合模式:只规定系统各个层次的最基础的一致行为,把组合本身的方法放到自身当中。
代码如下(示例):抽象公共方法组件
/// <summary>
/// 抽象公共方法组件
/// </summary>
public abstract class Company_Components
{
public string name { get; set; }
public Company_Components(string name)
{
this.name = name;
}
public abstract string Operation();
}
代码如下(示例):实现组件,并扩展枝节点方法
/// <summary>
/// 实现枝节点
/// </summary>
public class Company_Composites : Company_Components
{
public string name { get; set; }
public List<Company_Components> company_Components;
public Company_Composites(string name) : base(name)
{
this.name = name;
this.company_Components = new List<Company_Components>();
}
public override string Operation()
{
Console.WriteLine("组合节点" + name + "的操作");
return name;
}
public void AddChild(Company_Components component)
{
Console.WriteLine($"当前节点:{this.name}添加---{component.name}节点");
company_Components.Add(component);
}
public void RemoveChild(Company_Components component)
{
company_Components.Remove(component);
}
}
代码如下(示例):实现叶节点功能
/// <summary>
/// 实现叶节点
/// </summary>
public class Company_Leafs : Company_Components
{
public Company_Leafs(string name) : base(name)
{
}
public override string Operation()
{
Console.WriteLine("叶节点" + name + "的操作");
return name;
}
}
代码如下(示例):客户端调用
public void Client()
{
//创建根节点对象
Company_Composites component = new Company_Composites("component");
//Console.WriteLine($"当前节点:{component.name}");
//创建两个组合节点对象
Company_Composites composite1 = new Company_Composites("composite1");
Company_Composites composite2 = new Company_Composites("composite2");
//将两个组合节点对象添加到根节点
component.AddChild(composite1);
component.AddChild(composite2);
//给第一个组合节点对象添加两个叶子节点
Company_Components leaf1 = new Company_Leafs("leaf1");
Company_Components leaf2 = new Company_Leafs("leaf2");
composite1.AddChild(leaf1);
composite1.AddChild(leaf2);
//给第二个组合节点对象添加一个叶子节点和一个组合节点
Company_Leafs leaf3 = new Company_Leafs("leaf3");
Company_Composites composite3 = new Company_Composites("composite3");
composite2.AddChild(leaf3);
composite2.AddChild(composite3);
//给第二个组合节点下面的组合节点添加两个叶子节点
Company_Components leaf4 = new Company_Leafs("leaf4");
Company_Components leaf5 = new Company_Leafs("leaf5");
composite3.AddChild(leaf4);
composite3.AddChild(leaf5);
//执行所有节点的操作
// component.Operation();
}
透明组合模式及安全组合模式区别
- 透明模式组件方法对枝节点和叶节点是公开的。
- 安全模式只是封装的完全公共方法,针对枝节点操作单独封装。
总结
清楚的定义各层的复杂对象,表示对象的全部或部分层次。 让客户端忽略了层次的差异,方便对整个层次结构进行控制。 简化客户端代码。复合开闭原则。
限制类型时会较为复杂。使设计变得更加抽象。