装饰者模式记录

装饰者模式:是对继承的另一种体现,在子类很少的情况下使用继承是是比较方便的,但是随着子类越来越多,装饰者模式就能体现出好处了。

定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

目的:减少子类多的情况,能动态的搭配需要添加的东西。

一般的继承就是线性思维,需要什么就在上面写啥。

装饰者模式就是将利用(依赖倒置这点)将实现一个装饰盒子插口(实现抽象的装饰本文对应 HandCatchCakeDecorate),之后实现的插件模块(对应AddEggHandCatchCake和AddMeatFlossHandCatchCake)可以拔插式的安装或者去除。

这里不过多叙述为甚么需要装饰者模式,网上有很多生动的例子:如 https://www.cnblogs.com/of-fanruice/p/11565679.htmlhttps://www.jianshu.com/p/4a530a3c70af

上面两个其中有人拿煎饼果子举例,这里我个人喜欢手抓饼,我就以手抓饼来举例子;这里直接上代码如何实现装饰者模式

 1.首先定义一个抽象的手抓饼类

 public abstract class AbstractHandCatchCake
  {
      public abstract string Print();
  }

 2.实现手抓饼类

    public class HandCatchCake:AbstractHandCatchCake
    {
        public override string Print()
        { 
            return "手抓饼";
        }
    }

  实现完成后如果想在手抓饼里假如其他作料可以1.重新继承AbstractHandCatchCake,在对print();方法重写假如自己的方法。2.可以继承现有的HandCatchCake,在他的基础上重写。但是这种方式都是要在调用前写好,而且种类多就不和合适了,因为种类多,子类就多。

因此装饰者模式就出现了解决这尴尬显现。

在写装饰者代码前,先了解下①谁又被装饰了,②装饰者是谁,③该如何装饰:

①.被装饰的是HandCatchCake,要在他上面添加需要的作料。

②.在定义咋装饰者前,需要先(AbstractHandCatchCake)的一个扩展类,将这个抽象扩展成可以添加装饰类。

这里定义的类继承了抽象方法,定义成员变量,定义构造函数都是该抽象,目的是为了后面加装饰用;方法调用抽象的print();

这里的操作就像是制作一个盒子模型,将需要的装饰的放上去。

这里需要注意他的定义都是使用抽象的,(依赖倒置)才能进行装饰。

    public class HandCatchCakeDecorate:AbstractHandCatchCake
    {
        
        private AbstractHandCatchCake handCatchCake;
        public HandCatchCakeDecorate(AbstractHandCatchCake handCatchCake) 
        {
            this.handCatchCake = handCatchCake;
        }
        public override string Print()
        {
            return handCatchCake.Print();
        }
    }

 

装饰者是主动去装饰那个人,这里我使用了两个装饰者一个添加蛋,一个添加肉松.

 class AddEggHandCatchCake:HandCatchCakeDecorate
    {
        public AddEggHandCatchCake(AbstractHandCatchCake handCatchCake) : base(handCatchCake) { }
        public override string Print()
        {
            return base.Print()+ AddEgg();

        }
        public string AddEgg() {
            return "添加一个蛋";
        }
    }

  

class AddMeatFlossHandCatchCake: HandCatchCakeDecorate
    {
        public AddMeatFlossHandCatchCake(AbstractHandCatchCake handCatchCake) : base(handCatchCake) { }
        public override string Print()
        {
            return base.Print()+ AddMeatFloss();

        }
        public string AddMeatFloss() {
            return "添加一份肉松";
        }
    }

  他们都继承那个被装饰的HandCatchCakeDecorate,并且都有自己的print方法,加蛋方法里是base.Print()+ AddEgg();就是在原基础上加了个蛋;加肉松也是一样的。

③该如何装饰

上面的被装饰是HandCatchCake(手抓饼实例)我们就需要在(手抓饼)上面添加蛋和肉松或其他想要的,就像堆叠在上面一样。

调用方式;

 static void Main(string[] args)
        {
            AbstractHandCatchCake hcc = new HandCatchCake();
            hcc.Print();
            //动态添加装饰者
            //加了两个蛋
            AbstractHandCatchCake hccAddEgg1 = new AddEggHandCatchCake(hcc);
            AbstractHandCatchCake hccAddEgg2 = new AddEggHandCatchCake(hccAddEgg1);
            //加了份肉松
            AddMeatFlossHandCatchCake hccAddMeatFloss = new AddMeatFlossHandCatchCake(hccAddEgg2);
            string s= hccAddMeatFloss.Print();
       Console.OutputEncoding = System.Text.Encoding.UTF8; Console.WriteLine(s); Console.ReadLine(); }

结果

 

 最后总结下

好处:1.在不改变对象情况下能加入新的,运行时才添加新的。

   2.更加自由,能自由的搭配选择,自己更加简单的选择装饰内容。

缺点:1.需要写更多的代码

   2.如果过多的装饰在调试时会增加很多工作量。

使用范围:对灵活,多组和的场景特别适用,在C#里BufferedStream就属于装饰者模式的体现。

posted @ 2020-05-18 17:29  蔡老板2019  阅读(117)  评论(0编辑  收藏  举报