设计模式——装饰模式

Posted 苹果园dog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式——装饰模式相关的知识,希望对你有一定的参考价值。

一、简介

装饰模式(Decorator)又名包装器(Wrapper),属于结构型模式的一种,采用递归的思想,用于包装类,使其功能丰富。

例如:有一个统计图表控件,可能需要有图/表切换的功能(切换按钮),也可能需要添加一个下拉框,用于过滤统计图表某个指标,

这些附加的功能根据不同的应用场景而不同,此时可以考虑采用装饰模式,动态为原始统计图表对象添加功能。

二、类图(引用GoF)

Component是原型类,被装饰的对象;

ConcreteComponet继承于Component,具体原型类;

Decorator是装饰基类,用于装饰Component,继承于Component,且拥有(关联)一个Component对象;

ConcreteDecoratorA和ConcreteDecoratorB为Decorator的派生类。

三、例子

在实际应用中,可以灵活运用装饰模式,可以没有具体原型类,也可以没有装饰基类。

下面通过一组例子详细介绍其用法。

1、装饰原型类的方法,为方法添加功能(包含具体原型类和装饰基类)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 装饰模式
{
    //=============================装饰方法SetA()================================
    /// <summary>
    /// 原型类
    /// </summary>
    public class BaseObject0
    {
        private string a;
        public virtual void SetA()
        {

        }
    }

    public class DrivedObject0 : BaseObject0
    {
        public override void SetA()
        {
            base.SetA();
        }
    }

    /// <summary>
    /// 装饰基类
    /// </summary>
    public class DecorateBase0 : BaseObject0
    {
        private BaseObject0 obj = null;
        public DecorateBase0(BaseObject0 boj)
        {
            this.obj = boj;
        }

        public override void SetA()
        {
            if (obj!=null)
            {
                obj.SetA();
            }
        }
    }

    //=============================================================
    /// <summary>
    /// 装饰子类A
    /// </summary>
    public class Adecorate0 : DecorateBase0
    {
        public Adecorate0(BaseObject0 boj)
            : base(boj)
        {

        }
        public override void SetA()
        {            
            base.SetA();
            Console.WriteLine("Adecorate0" + System.Environment.NewLine);
        }
    }

    //============================================================
    /// <summary>
    /// 装饰子类B
    /// </summary>
    public class Bdecorate0 : DecorateBase0
    {
        public Bdecorate0(BaseObject0 boj)
            : base(boj)
        {

        }
        public override void SetA()
        {
            base.SetA();
            Console.WriteLine("Bdecorate0" + System.Environment.NewLine);
        }
    }
}

调用:

Bdecorate0 bdecorate = new Bdecorate0(new Adecorate0(new BaseObject0()));
            bdecorate.SetA();
            Console.ReadKey();

结果:

2、通过方法装饰类的字段或属性(不包含具体原型类和装饰基类)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 装饰模式
{
    //=============================装饰字段a================================
    /// <summary>
    /// 原型类
    /// </summary>
    public class BaseObject4
    {
        public string a;
        public virtual void SetA()
        {

        }
    }

    /// <summary>
    /// 装饰基类
    /// </summary>
    public class DecorateBase4:BaseObject4
    {
        protected BaseObject4 obj = null;
        public DecorateBase4(BaseObject4 boj)
        {
            this.obj = boj;
        }
    }

    //=============================================================
    /// <summary>
    /// 装饰子类A
    /// </summary>
    public class Adecorate4 : DecorateBase4
    {
        public Adecorate4(BaseObject4 boj)
            : base(boj)
        {
 
        }
        public override void SetA()
        {
            obj.SetA();
            a = obj.a + "Adecorate" + System.Environment.NewLine;
        }
    }

    //============================================================
    /// <summary>
    /// 装饰子类B
    /// </summary>
    public class Bdecorate4 : DecorateBase4
    {
        public Bdecorate4(BaseObject4 boj)
            : base(boj)
        {
 
        }
        public override void SetA()
        {
            obj.SetA();//Adecorate4(obj)的a的值为"Adecorate"
            a = obj.a + "Bdecorate" + System.Environment.NewLine;
        }
    }
}

调用:

Bdecorate4 bdecorate = new Bdecorate4(new Adecorate4(new BaseObject4()));
            bdecorate.SetA();
            Console.WriteLine(bdecorate.a);
            Console.ReadKey();

效果同上

3、装饰方法(包含装饰基类,不包含具体原型类)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 装饰模式
{
    /// <summary>
    /// 原型类
    /// </summary>
   public class BaseObject
    {
       private string a;
       public virtual string GetA()
       {
           return a;
       }
    }

    /// <summary>
    /// 装饰基类
    /// </summary>
   public class decorator : BaseObject
   {
       BaseObject obj = null;
       public decorator(BaseObject bojPara)
       {
           this.obj = bojPara;
       }

       public override string GetA()
       {
           return obj.GetA();
       }
   }

    /// <summary>
    /// 装饰子类A
    /// </summary>
   public class Adecorate : decorator
   {
       public Adecorate(BaseObject boj)
           :base(boj)
       {

       }
       public override string GetA()
       {
           return base.GetA() + "Adecorate";
       } 
   }

   /// <summary>
   /// 装饰子类B
   /// </summary>
   public class Bdecorate : decorator
   {
       public Bdecorate(BaseObject boj)
           : base(boj)
       {

       }
       public override string GetA()
       {
           return base.GetA() + "Bdecorate";
       }
   }

}

调用:

Bdecorate bdecorate = new Bdecorate(new Adecorate(new BaseObject()));
            Console.WriteLine(bdecorate.GetA());            
            Console.ReadKey(); 

效果同上

4、装饰方法(不包含装饰基类和具体原型类)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 装饰模式
{

    /// <summary>
    /// 原型类
    /// </summary>
    public class BaseObject2
    {
        private string a;
        public virtual string GetA()
        {
            return a;
        }
    }


    /// <summary>
    /// 装饰类A
    /// </summary>
    public class Adecorate2:BaseObject2 
    {
        BaseObject2 obj = null;
        public Adecorate2(BaseObject2 boj)
        {
            this.obj = boj;
        }

        public override string GetA()
        {
            return obj.GetA() + "Adecorate" + System.Environment.NewLine;
        }
    }

    /// <summary>
    /// 装饰类B
    /// </summary>
    public class Bdecorate2 : BaseObject2 
    {
        BaseObject2 obj = null;
        public Bdecorate2(BaseObject2 boj)
        {
            this.obj = boj;
        }

        public override string GetA()
        {
            return obj.GetA() + "Bdecorate" + System.Environment.NewLine;
        }
    }

}

调用:

 Bdecorate2 bdecorate = new Bdecorate2(new Adecorate2(new BaseObject2()));
            Console.WriteLine(bdecorate.GetA());
            Console.ReadKey(); 

效果同上。.

5、通过方法装饰字段或属性(无装饰基类和具体原型类)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 装饰模式
{

    
    /// <summary>
    /// 原型类
    /// </summary>
    public class BaseObject3
    {
        public string a;
        public virtual void SetA()
        {
            
        }
    }

    //=============================================================
    /// <summary>
    /// 装饰类A
    /// </summary>
    public class Adecorate3 : BaseObject3
    {
        BaseObject3 obj = null;
        public Adecorate3(BaseObject3 boj)
        {
            this.obj = boj;
            
        }

        public override void SetA()
        {            
             obj.SetA();
             a = obj.a + "Adecorate" + System.Environment.NewLine;
        }
    }

    //============================================================
    /// <summary>
    /// 装饰类B
    /// </summary>
    public class Bdecorate3 : BaseObject3
    {
        BaseObject3 obj = null;        
        public Bdecorate3(BaseObject3 boj)
        {
            this.obj = boj;
        }

        public override void SetA()
        {
            obj.SetA();//Adecorate3(obj)的a的值为"Adecorate"
            a=obj.a + "Bdecorate" + System.Environment.NewLine;
        }
    }
}

调用:

Bdecorate3 bdecorate = new Bdecorate3(new Adecorate3(new BaseObject3()));
            bdecorate.SetA();
            Console.WriteLine(bdecorate.a);
            Console.ReadKey();

方法同上。

 

以上是关于设计模式——装饰模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式---装饰者模式

设计模式之单例模式

Java设计模式之装饰者模式

装饰模式与代理模式的区别

设计模式之装饰器模式

设计模式-装饰者模式(Go语言描述)