• 装饰模式


    装饰模式适合的最恰当的形容词就是:子类复子类,子类何其多。 如果一个基类有多个子类,而各个子类可能具有不同的功能,同一个子类也可能具有不同的功能,如果我们将一个功能定义为实现一个接口,那么同一个子类要实现不同的功能,那么他要在子类的基础上继续创建子类,无穷无尽。。。

    例子使用:坦克分为T50与T75,坦克具有基本的发射与移动功能,其中具有附加功能(红外功能、水陆两栖功能、卫星定位功能)

    如果我们不使用装饰模式的话,那么我们实现的代码:

    #region 抽象坦克基类
        public abstract class Tank
        {
            public abstract void Shot();
            public abstract void Run();
        }
        #endregion
      #region 具体坦克类
        public class Tank50 : Tank
        {
            public override void Run()
            {
                Console.WriteLine(this.GetType().Name+"在奔跑");
            }
    
            public override void Shot()
            {
                Console.WriteLine(this.GetType().Name + "在发射炮弹");
            }
        }
        public class Tank75 : Tank
        {
            public override void Run()
            {
                Console.WriteLine(this.GetType().Name + "在奔跑");
            }
    
            public override void Shot()
            {
                Console.WriteLine(this.GetType().Name + "在发射炮弹");
            }
        }
        #endregion
      #region 功能接口
        interface IRedLine
        {
            void RedLine();
        }
        interface IWaterPath
        {
            void WaterPath();
        }
        interface IPosition
        {
            void IPosition();
        }
        #endregion
      #region 功能坦克类
        public class Tank50A : Tank50, IRedLine
        {
            public void RedLine()
            {
                Console.WriteLine("具有红外功能");
            }
        }
        public class Tank50B : Tank50, IRedLine,IWaterPath
        {
            public void RedLine()
            {
                Console.WriteLine("具有红外功能");
            }
    
            public void WaterPath()
            {
                Console.WriteLine("具有水陆两栖功能");
            }
        }
        //无限扩展
        //......
        #endregion

    装饰模式避免了这种问题,它的设计思路不是将功能化为接口,而是将每个功能实现在每个装饰类中。

    坦克类仍然不变,如下:

       #region 抽象坦克基类
        public abstract class Tank
        {
            public abstract void Shot();
            public abstract void Run();
        }
        #endregion
     #region 具体坦克类
        public class Tank50 : Tank
        {
            public override void Run()
            {
                Console.WriteLine(this.GetType().Name+"在奔跑");
            }
    
            public override void Shot()
            {
                Console.WriteLine(this.GetType().Name + "在发射炮弹");
            }
        }
        public class Tank75 : Tank
        {
            public override void Run()
            {
                Console.WriteLine(this.GetType().Name + "在奔跑");
            }
    
            public override void Shot()
            {
                Console.WriteLine(this.GetType().Name + "在发射炮弹");
            }
        }
        #endregion

    装饰类如下:

      #region 装饰基类
        public abstract class Decorator :Tank
        {
            private Tank _tank;
            public Decorator(Tank tank)
            {
                _tank = tank;
            }
            public override void Run()
            {
                _tank.Run();
            }
            public override void Shot()
            {
                _tank.Shot();
            }
        }
        #endregion
      #region 具体功能装饰类
        public class DecoratorRedLine : Decorator
        {
            public DecoratorRedLine(Tank tank) : base(tank)
            {
    
            }
            public override void Run()
            {
                base.Run();
            }
            public override void Shot()
            {
                Console.WriteLine("具有红外功能");
                base.Shot();//这里就是重点!!!!可以调用构造函数实例时的基成员方法
            }
        }
        public class DecoratorWaterPath : Decorator
        {
            public DecoratorWaterPath(Tank tank) : base(tank)
            {
    
            }
            public override void Run()
            {
                base.Run();
            }
            public override void Shot()
            {
                Console.WriteLine("具有水陆两栖功能");
                base.Shot();
            }
        }
        public class DecoratorPosition : Decorator
        {
            public DecoratorPosition(Tank tank) : base(tank)
            {
    
            }
            public override void Run()
            {
                base.Run();
            }
            public override void Shot()
            {
                Console.WriteLine("具有定位功能");
                base.Shot();
            }
        }
        #endregion
     static void Main(string[] args)
            {
                Tank tank = new Tank50();//实例化一个坦克类
                Decorator decorator = new DecoratorRedLine(tank);
                Decorator decorator2 = new DecoratorWaterPath(decorator);//这个shot时会调用decorator的shot,从而实现不断叠加
                decorator2.Shot();
                Console.ReadKey();
            }

    装饰类,将各个需要随时变化的功能写在装饰的子类中,当需要使用的时候只需要调用相应的装饰子类,重点就是调用base.shot()  base的方法 ,因此在装饰的抽象类中,必须调用对需要装饰类的方法的复写,这样才能实现base的方法! 

    设计模式的思想真的是非常好,多学,多做,多练,加油!

  • 相关阅读:
    ABP 番外篇-容器
    ABP 番外篇-菜单
    三、写服务
    十二、异步
    一、PHP_OSS使用
    十一、泛型
    Automapper
    ABP实践学习
    【2019-07-26】省是缺点
    【2019-07-25】女人,很强大
  • 原文地址:https://www.cnblogs.com/ningxinjie/p/12213437.html
Copyright © 2020-2023  润新知