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

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

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

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

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

    装饰者模式就是将利用(依赖倒置这点)将实现一个装饰盒子插口(实现抽象的装饰本文对应 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就属于装饰者模式的体现。

  • 相关阅读:
    深入JAVA注解之属性注解
    深入JAVA注解之方法注解
    C# 启动外部程序的几种方法
    在.NET中实现彩色光标/动画光标和自定义光标[转]
    C#实现汉诺塔问题
    ExecuteNonQuery()返回值注意点
    在VS2012下不安装VS2010编译VS2010的工程
    Windows 窗体的.Net 框架绘图技术
    使用DataSet Datatable 更新数据库的三种方式
    C#.net 之货币转换
  • 原文地址:https://www.cnblogs.com/liuyang95/p/12911147.html
Copyright © 2011-2022 走看看