组合模式

一、定义

将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得对单个对象和组合对象的使用具有一致性。

二、应用实例

文件系统中的文件与文件夹、Winform中的简单控件与容器控件、XML中的Node和Element等。

透明模式

透明模式是把组合使用的方法放到抽象类中,使得叶子对象和枝干对象具有相同的结构,客户端调用时具备完全一致的行为接口。但因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的,违背了单一职责原则和里氏替换原则。

安全模式

安全模式是把枝干和叶子节点区分开来,枝干单独拥有用来组合的方法,这种方法比较安全。但枝干和叶子节点不具有相同的接口,客户端的调用需要做相应的判断,违背了依赖倒置原则。

三、优缺点

优点

  • 客户端调用简单,可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
  • 可以方便的在结构中增加或者移除对象。

缺点

  • 客户端需要花更多时间理清类之间的层次关系

四、示例

 

下面代码是用透明模式实现的

1.Component.cs

public abstract class Component
    {
        public string Name { get; set; }

        public Component(string name)
        {
            this.Name = name;
        }

        public abstract int SumArticleCount();
public abstract void Add(Component component);
public abstract void Remove(Component component); public abstract void Display(int depth); }

2.Composite.cs

public class Composite : Component
    {
        private List<Component> _components = new List<Component>();

        public Composite(string name):base(name)
        {
        }
public override void Add(Component component) { _components.Add(component); } public override void Remove(Component component) { _components.Remove(component); } public override void Display(int depth) { Console.WriteLine(new string('-', depth) + Name); foreach (Component component in _components) { component.Display(depth + 1); } } public override int SumArticleCount() { int count = 0; foreach (var item in _components) { count += item.SumArticleCount(); } return count; } }

3.Leaf.cs

public class Leaf : Component
    {
        public Leaf(string name) : base(name)
        {
        }

        public override void Add(Component component)
        {
            throw new InvalidOperationException("叶子节点不能添加元素");
        }

        public override void Remove(Component component)
        {
            throw new InvalidOperationException("叶子节点不能删除元素");
        }

        public override int SumArticleCount()
        {
            return 1;
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + Name);
        }
    }

4.Program.cs

internal class Program
    {
        static void Main(string[] args)
        {
            Component root = new Composite("目录");

            Component music = new Composite("音乐");
            Component knowledge = new Composite("知识");
            Component life = new Composite("生活");
            root.Add(music);
            root.Add(knowledge);
            root.Add(life);

            Component science = new Composite("科学科普");
            Component tech = new Composite("野生技术协会");
            knowledge.Add(science);
            knowledge.Add(tech);

            Component scienceArticle1 = new Leaf("科学科普文章1");
            Component scienceArticle2 = new Leaf("科学科普文章2");
            science.Add(scienceArticle1);
            science.Add(scienceArticle2);

            Component shoot = new Composite("摄影");
            Component program = new Composite("编程");
            Component english = new Composite("英语");
            tech.Add(shoot);
            tech.Add(program);
            tech.Add(english);

            Component shootArticle1 = new Leaf("摄影文章1");
            Component lifeArticle1 = new Leaf("生活文章1");
            Component lifeArticle2 = new Leaf("生活文章2");
            shoot.Add(shootArticle1);
            life.Add(lifeArticle1);
            life.Add(lifeArticle2);
           
            root.Display(0);
            Console.WriteLine("文章数:" + root.SumArticleCount());
        }
    }

运行结果:

 

posted on 2023-05-30 16:57  一只向上爬的小蜗牛  阅读(3)  评论(0编辑  收藏  举报