zoukankan      html  css  js  c++  java
  • 设计模式(14)---组合模式

    一、定义

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

    解释:简单来说,编写一个类,该类能作用于整体,并且编写整体中的部分时也能使用该类,而不用做大的更改。

    二、UML类图及基本代码

    基本代码:

    abstract class Component
        {
            protected string name;
    
            public Component(string name)
            {
                this.name = name;
            }
    
            public abstract void Add(Component component);
            public abstract void Remove(Component component);
            public abstract void Display(int depth);
        }
    
        class Leaf : Component
        {
            public Leaf(string name)
                : base(name)
            { }
    
            public override void Add(Component component)
            {
                Console.WriteLine("cannot add to a leaf");
            }
    
            public override void Remove(Component component)
            {
                Console.WriteLine("cannot remove to a leaf");
            }
    
            public override void Display(int depth)
            {
                Console.WriteLine(new string('-', depth) + name);
            }
        }
    
        class Composite : Component
        {
            private IList<Component> children = new List<Component>();
    
            public Composite(string name)
                : base(name)
            { }
    
            public override void Add(Component component)
            {
                children.Add(component);
            }
    
            public override void Remove(Component component)
            {
                children.Remove(component);
            }
    
            public override void Display(int depth)
            {
                Console.WriteLine(new string('-', depth) + name);
    
                foreach (Component component in children)
                {
                    component.Display(depth + 2);
                }
            }
        }

    客户端进行调用:

    Composite root = new Composite("root");
                root.Add(new Leaf("leaf A"));
                root.Add(new Leaf("leaf B"));
    
                Composite composite = new Composite("Composite X");
                composite.Add(new Leaf("leaf XA"));
                composite.Add(new Leaf("leaf XB"));
                root.Add(composite);
    
                Composite composite2 = new Composite("Composite XY");
                composite2.Add(new Leaf("leaf XYA"));
                composite2.Add(new Leaf("leaf XYB"));
                composite.Add(composite2);
    
                root.Add(new Leaf("leaf C"));
    
                Leaf leaf = new Leaf("Leaf D");
                root.Add(leaf);
                root.Remove(leaf);
    
                root.Display(1);
    View Code

    结果如图:

    三、透明方式和安全方式

      基本代码中,leaf类也有add和remove方法,也就是说Component声明所有用来管理子对象的方法,实现了所有子类都具备其方法的目的。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但因为leaf不具备add和remove的功能,所以实现它是没有意义的。这种方式就是透明方式。

      安全方式是叶节点和枝节点不具有相同的接口,由于不够透明,那么客户端调用时需要做相应的判断,带来了不便。所以在实际项目中使用安全方式和透明方式就需要视情况而定。

    四、举例说明:

      绘制一个图形,该图形由一个复杂图形和两条线段组成。可以自由的移除该图形。

    public abstract class Graphics
        {
            public string Name { get; set; }
            public Graphics(string name)
            {
                this.Name = name;
            }
    
            public abstract void Draw();
            public abstract void Add(Graphics graphics);
            public abstract void Remove(Graphics graphics);
        }
    
        public class Line : Graphics
        {
            public Line(string name)
                : base(name)
            { }
    
            public override void Draw()
            {
                Console.WriteLine("" + Name);
            }
    
            public override void Add(Graphics graphics)
            {
                throw new Exception("不能向简单图形line添加图形");
            }
    
            public override void Remove(Graphics graphics)
            {
                throw new Exception("不能向简单图形line移除图形");
            }
        }
    
        public class Circle : Graphics
        {
            public Circle(string name)
                : base(name)
            { }
    
            public override void Draw()
            {
                Console.WriteLine("" + Name);
            }
    
            public override void Add(Graphics g)
            {
                throw new Exception("不能向简单图形Circle添加其他图形");
            }
            public override void Remove(Graphics g)
            {
                throw new Exception("不能向简单图形Circle移除其他图形");
            }
        }
    
        public class ComplexGraphics : Graphics
        {
            private IList<Graphics> complexGraphicsList = new List<Graphics>();
    
            public ComplexGraphics(string name)
                : base(name)
            { }
    
            public override void Draw()
            {
                foreach (Graphics g in complexGraphicsList)
                {
                    g.Draw();
                }
            }
    
            public override void Add(Graphics graphics)
            {
                complexGraphicsList.Add(graphics);
            }
    
            public override void Remove(Graphics graphics)
            {
                complexGraphicsList.Remove(graphics);
            }
        }

    客户端调用:

    ComplexGraphics complexGraphics = new ComplexGraphics("一个复杂图形和两条线段组成的复杂图形");
                complexGraphics.Add(new Line("线段A"));
                ComplexGraphics complexGraphics2 = new ComplexGraphics("一个圆和一条线组成的复杂图形");
                complexGraphics2.Add(new Circle(""));
                complexGraphics2.Add(new Line("线段B"));
                complexGraphics.Add(complexGraphics2);
                Line line = new Line("线段C");
                complexGraphics.Add(line);
    
                Console.WriteLine("复杂图形的绘制如下:");
                Console.WriteLine("----------------------");
                complexGraphics.Draw();
                Console.WriteLine("复杂图形的绘制完成");
                Console.WriteLine("----------------------");
    
                complexGraphics.Remove(line);
                Console.WriteLine("移除线段C后,复杂图形的绘制如下:");
                Console.WriteLine("---------------------");
                complexGraphics.Draw();
                Console.WriteLine("复杂图形绘制完成");
                Console.WriteLine("---------------------");
    View Code

    调用结果:

    五、优缺点及适用场景

    优点:

    1)组合模式使得客户端可以一致的处理对象和对象容器,既是叶节点和枝节点。

    2)更容易的为组合对象添加新的组件。

    3)解耦了客户端与复杂对象。

    缺点:

    设计更加复杂。

    适用场景:

    1)需要表示一个对象整体和部分的层次结构

    2)用户希望忽略组合对象和单个对象的不同,一致的处理组合对象和单个对象。

  • 相关阅读:
    Hunspell介绍及试用
    语音活性检测器py-webrtcvad安装使用
    Nginx处理请求的11个阶段(agentzh的Nginx 教程学习记录)
    搭建rsync服务并同步重要数据
    语料库基础学习
    解决SSH远程执行命令找不到环境变量的问题
    Centos7上安装、破解bamboo6.0.3
    Java代码走查具体考察点
    Bamboo基础概念
    安装OpenResty开发环境
  • 原文地址:https://www.cnblogs.com/ysyn/p/4125969.html
Copyright © 2011-2022 走看看