最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

看热讯:C#设计模式09——组合模式的写法

来源:博客园

1. 什么是C#组合模式?

组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“整体/部分”层次结构。使用此模式,客户端可以按相同的方式处理单个对象和对象集合,而不必关注它们是单个对象还是组合对象。组合对象本身也可以作为容器,包含其他组合对象,形成更复杂的树形结构。


(资料图)

在C#中,组合模式是一种递归嵌套的设计模式,通常需要使用抽象类或接口表示“整体”和“部分”之间的关系,并将部件对象存储在它们的容器中。通过通过将容器中的部件继续使用相同的方式处理,客户端代码可以逐级访问嵌套对象,而不必知道每个对象的具体类型或是否是叶子节点。

2. 为什么要使用C#组合模式?

组合模式可以方便地处理层次结构,例如组织机构、文件系统或UI控件。使用该模式,可以将树形数据结构的遍历变得简单且具有一致性,而无论遍历哪个节点,只需按照相同的方式进行。

使用组合模式还可以使代码更加灵活。由于容器和叶子节点可以互换使用,可以轻松地添加新的叶子节点和容器对象,而不会影响其它部分代码的实现。

3. 组合模式的主要角色有哪些?

C#组合模式通常涉及四个主要角色:

- 抽象组件(Component): 定义组合关系的抽象类或接口,为容器和叶子节点共享的操作提供通用的实现。- 叶子节点(Leaf): 组合树结构中的最底层元素,它们没有子节点,具有特定的行为。- 容器(Composite): 包含一组子节点并维护它们之间的组合结构。容器可以包含其他容器和叶子节点,统一对子节点操作。- 客户端(Client): 使用组合结构的代码,通常通过容器操作组合节点,而不必关注如何管理节点之间的组合关系,将复杂度降到最低。

4. 组合模式如何实现?

组合模式的一个常见实现方案是将组件抽象成接口或抽象类。这个抽象类包含容器和叶子节点的通用行为和属性,并定义了添加、删除和获取子节点的方法。容器实现这个抽象类,并维护它们的子节点,而叶子节点扩展它们自己的逻辑。

通常情况下,容器会将它自己的操作通过递归调用委托给子节点,从而在深层次的嵌套结构中完成某个指定操作。客户端代码使用这个抽象接口或类,而不是具体的实现对象,实现了透明的管理树形结构元素。

5. 组合模式有哪些优缺点?

优点:

- 可以方便地处理树状结构,具有一致性和可维护性。- 组合对象可以递归嵌套,允许动态的添加和删除节点和树形结构。- 通过共享相同接口或抽象类,客户端代码可以无缝切换一个元素与多个元素之间的关系,从而简化代码逻辑。- 允许在叶子和组合对象中分别添加新的行为和操作,而不会影响其它部分的代码。

缺点:

- 可能难以限制容器中的元素类型,会产生一定的安全隐患。- 由于递归嵌套,可能对内存和性能有一定的影响。- 当组合对象拥有大量子节点时,可能会对代码可读性和理解性造成一定的困难。

以下是一个使用C#组合模式的示例代码:

//抽象组件public abstract class Component{    protected string Name;    public Component(string name)    {        Name = name;    }    public abstract void Add(Component c);    public abstract void Remove(Component c);    public abstract void Display(int depth);}//叶子节点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);    }}//容器public class Composite : Component{    private List _children = new List();    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)    {        Console.WriteLine(new string("-", depth) + Name);        foreach (Component component in _children)        {            component.Display(depth + 2);        }    }}//客户端class Client{    static void Main(string[] args)    {        Composite root = new Composite("root");        root.Add(new Leaf("Leaf A"));        root.Add(new Composite("Composite X"));        Composite compositeY = new Composite("Composite Y");        compositeY.Add(new Leaf("Leaf B"));        compositeY.Add(new Leaf("Leaf C"));        root.Add(compositeY);        Leaf leafD = new Leaf("Leaf D");        root.Add(leafD);        root.Remove(leafD);        root.Display(1);        Console.ReadKey();    }}

在上述代码中,抽象组件是Component类,其中包含添加、删除和展示子节点等公共方法。叶子节点Leaf和容器Composite分别继承了Component,并实现了它们自己的逻辑。客户端使用抽象组件Component来透明地处理叶子节点和容器对象,并对它们进行操作。在Main方法中,创建了一个根容器对象,并添加了一些叶子节点和容器对象。输出结果是一个树形结构。

-root--Leaf A--Composite X--Composite Y---Leaf B---Leaf C

其中,输出的内容是按照树形结构展示的,每行前面添加了一些连字符("-")来表示层次结构深度。可以看到,root节点包含了三个子节点,其中compositeY节点又包含了两个子节点。最后,“Leaf D”节点被移除了。

关键词: