zoukankan      html  css  js  c++  java
  • 装饰者模式

      装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

        装饰者模式隐含的是通过一条条装饰链去实现具体对象,每一条装饰链都始于一个Componet对象,每个装饰者对象后面紧跟着另一个装饰者对象,而对象链终于ConcreteComponet对象。

      用粗略的话讲:装饰模式就是为已有功能动态地添加更多功能的一种方式。

      何为动态。比如打折策略。3折后再减30元再打8折,

      UML图如下:

        

      Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰着抽象类,继承了Component从外类来扩展Component类的功能,但对于Component来说,就无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象。起到给Component添加职责的功能。

      实现代码示例:

      装饰模式是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了。每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。

      示例:

    namespace 装饰者模式
    {
        class Program
        {
            static void Main(string[] args)
            {
                ConcreateComponent c = new ConcreateComponent();
                ConcreteDecorator眉毛 d1 = new ConcreteDecorator眉毛();
                ConcreteDecorator头发 d2 = new ConcreteDecorator头发();
    
                d1.SetComponent(c);     //d1里面放入c,是为了调用原始c的 捕获素颜美女
                d2.SetComponent(d1);    //d1是画过眉毛的
                d2.Operation();
    
                Console.ReadKey();
            }
        }  
    
        abstract class Component
        {
            public abstract void Operation();
        }
    
        class ConcreateComponent : Component
        {
            //原始内容,具体装饰类都会调用一次
            public override void Operation()
            {
                Console.WriteLine("捕获素颜美女一个!");
            }
        }
    
        abstract class Decorator : Component
        {
            //里面放一个父接口
            protected Component component;
    
            public void SetComponent(Component component)   //设置Component
            {
                this.component = component;
            }
    
            public override void Operation()    //用接收到的Component的Operation方法来重写父Component接口的Operation方法
            {
                if (component != null)
                {
                    component.Operation();
                }
            }
        }
    
        class ConcreteDecorator眉毛 : Decorator
        {
            private string addedState;      //代表画眉毛的实际操作
    
            public override void Operation()
            {
                base.Operation();           //素颜美女(原始内容)
                Console.WriteLine("帮美女画画眉!");
                addedState = "眉毛漂亮了!";    //实际装饰内容
            }
        }
    
        class ConcreteDecorator头发 : Decorator
        {
            public override void Operation()
            {
                base.Operation();           //原始内容
                Console.WriteLine("帮美女梳梳头!");
                AddedBehavior();            //实际装饰内容
            }
    
            private void AddedBehavior()    //本类独有的方法,以区别于ConcrateDecoratorA
            {
                Console.WriteLine("头发变精神了!");
            }
        }
    }

      这个示例写得不错,基本上掌握了装饰者的作用。

      

      装饰者模式的应用场景:

    1. 想透明并且动态地给对象增加新的职责的时候。
    2. 给对象增加的职责,在未来存在增加或减少可能。
    3. 用继承扩展功能不太现实的情况下,应该考虑用组合的方式。

      装饰者模式的优点:

    1. 通过组合而非继承的方式,实现了动态扩展对象的功能的能力。
    2. 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
    3. 充分利用了继承和组合的长处和短处,在灵活性和扩展性之间找到完美的平衡点。
    4. 装饰者和被装饰者之间虽然都是同一类型,但是它们彼此是完全独立并可以各自独立任意改变的。
    5. 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

      装饰者模式的缺点:

    1. 装饰链不能过长,否则会影响效率。
    2. 因为所有对象都是继承于Component,所以如果Component内部结构发生改变,则不可避免地影响所有子类(装饰者和被装饰者),也就是说,通过继承建立的关系总是脆弱地,如果基类改变,势必影响对象的内部,而通过组合(Decoator HAS A Component)建立的关系只会影响被装饰对象的外部特征。
    3. 只在必要的时候使用装饰者模式,否则会提高程序的复杂性,增加系统维护难度。
  • 相关阅读:
    时间模块(二)datetime
    xmltodict模块
    C和指针
    C和指针指针
    笔试2
    istream_iterator,ostream_iterator与vector的转换
    C++工厂方法与反射的简单实现
    rpcndr.h和wtypes.h冲突Bug的解决方案
    ubuntu 9.04 安装mysql
    QT in Ubuntu cannot find lfreetype
  • 原文地址:https://www.cnblogs.com/qixuejia/p/4370272.html
Copyright © 2011-2022 走看看