设计模式深入学习---Decorator装饰模式(结构型模式)

   我们先理解下什么情况会用到Decorator装饰模式。  

   比如我们设计一个游戏人物,人物拥有的装扮,如衣服,裤子,靴子,手套,戒指,帽子 等 这些类型的开发,又或者是设计一个部件,比如一个武器凹槽,我们这个武器凹槽可以加 激光炮,加农炮,枪,防御盾。再或者我们制作游戏人物的技能框,里面可以有各种各样的技能。

   这些时候只要是在同一个部件下,这个部件可以拥有很多独立而且等级平行的单位对象时,我们就可以采用Decorator装饰模式来进行开发。首先来看看Decorator装饰模式的原理实现,上代码。

abstract class Component
  {
      public abstract void Operation();
  }
 
  class ConcreteComponent : Component
  {
      public override void Operation()
      {
          Console.WriteLine("具体对象的操作");
      }
  }
 
 
 
  abstract class Decorator : Component
  {
      protected Component component;
 
      public void SetComponent(Component component)
      {
          this.component = component;
      }
      public override void Operation()
      {
          component.Operation();
      }
  }
 
 
 
  class ConcreteDecoratorA : Decorator
  {
      private string addedState;
 
      public override void Operation()
      {
          base.Operation();
          addedState = "New State";
          Console.WriteLine("具体装饰对象A的操作");
      }
  }
 
  class concreteDecoratorB : Decorator
  {
      public override void Operation()
      {
          base.Operation();
          AddedBehavior();
          Console.WriteLine("具体装饰对象B的操作");
      }
      private void AddedBehavior()
      {
 
      }
  }
   代码里先定义了一个Component的抽象父类,有一个Operation方法。然后定义一个操作对象的子类 ConcreteComponent 。来执行具体的操作逻辑。 这时候我们就可以定义一个装饰类Decorator 了,装饰类继承Component 。再多了一个SetComponent方法,用来把外部传输进来的其他装饰类保存下来,而且自身的执行方法Operation也是调用被传进来的类方法。  最后,我们就声明两个实体的装饰类AConcreteDecoratorA 和ConcreteDecoratorB ,都继承Decorator 装饰类。 装饰类A有一个独有的 string 字段。 装饰类B有一个独有的AddedBehavior()方法,这两个用来区分下它们两个的不同之处。然后我们来调用一下,并且看看运行效果。 
public static void Mains()
   {
       ConcreteComponent c = new ConcreteComponent();
       ConcreteDecoratorA d1 = new ConcreteDecoratorA();
       concreteDecoratorB d2 = new concreteDecoratorB();
       d1.SetComponent(c);
       d2.SetComponent(d1);
       d2.Operation();
       Console.ReadKey();
   }


   我们在Main方法里面声明了装饰操作类,装饰类A和B,然后装饰类A装饰装饰操作类, 装饰类B 装饰 装饰类A,然后装饰类B输出,这样就把每一次装饰的经过都调用了起来,有没有点 拼接火车的感觉,每一个装饰类就像一节节火车,都是接着火车头。这样就可以无限扩产下去。这就是Decorator装饰模式的基本使用原理。好,那我们现在理解了使用原理和使用环境,我们试着来设计一个 技能栏里面,我们往技能栏里面添加技能的效果。

static void Main(string[] args)
      {
          //Base.Mains();  //装饰模式 基础知识的调用 全部代码都在Base的类里面 取消注释就可以运行了
 
          SkillBar skill1 = new SkillBar("恶魔猎手");
          ManaBurn mb = new ManaBurn();
          Immolation ii = new Immolation();
          Evasion ev = new Evasion();
          Metamorphosis me = new Metamorphosis();
          mb.Decorate(skill1);
          ii.Decorate(mb);
          ev.Decorate(ii);
          me.Decorate(ev);
          me.Show();
 
          Console.WriteLine();
 
          SkillBar skill2 = new SkillBar("剑圣");
          WindWalk ww = new WindWalk();
          MirrorImage mi = new MirrorImage();
          CriticalStrike cs = new CriticalStrike();
          Bladestorm bl = new Bladestorm();
          ww.Decorate(skill2);
          mi.Decorate(ww);
          cs.Decorate(mi);
          bl.Decorate(cs);
          bl.Show();
 
 
 
          Console.ReadKey();
      }
  }
 
  class SkillBar
  {
      public SkillBar()
      {
 
      }
 
      private string name;
      public SkillBar(string name)
      {
          this.name = name;
            
      }
 
      public virtual void Show()
      {
          Console.WriteLine("--------------------{0}的技能条---------------------", name);
      }
  }
 
  //技能操作类
  class Skills : SkillBar
  {
      protected SkillBar component;
 
       
      public void Decorate(SkillBar component)
      {
          this.component = component;
      }
 
      public override void Show()
      {
          if (component != null)
          {
              component.Show();
          }
      }
  }
 
  //技能装饰类
 
 
  class ManaBurn : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(魔法燃烧):使敌人的魔法值成为同点伤害数(耗魔法75)");
          base.Show();
      }
  }
 
  class Immolation : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(献祭):造成周围伤害(耗魔法35");
          base.Show();
      }
  }
 
  class Evasion : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(闪避):英雄周围的我方士兵回避率增高(不需要使用即一直保持)");
          base.Show();
      }
  }
  class Metamorphosis : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(变身)把自己变成强力恶魔,远程攻击,体力加500,持续60秒(耗魔法150)。");
          base.Show();
      }
  }
 
 
 
  class WindWalk : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(风速行走):英雄隐身且快速移动");
          base.Show();
      }
  }
 
  class MirrorImage : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(镜像):召影子一起战斗,时间持续60秒。(耗魔法150)");
          base.Show();
      }
  }
 
  class CriticalStrike : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(强力伤害):周围部队造成更多伤害");
          base.Show();
      }
  }
 
 
 
  class Bladestorm : Skills
  {
      public override void Show()
      {
          Console.WriteLine("(大刀乱舞):乱砍周围地面敌人,每秒110伤害值");
          base.Show();
      }
  }
      调用一我们先声明了一个技能条类 SkillBar , 里面有一个Show方法。 然后声明一个技能操作类 Skills.继承SkillBar。里面有一个装饰方法Decorate和重写父类Show方法, 然后下面就是各个不同的技能类。都继承于技能操作类。 重写Show方法,处理自己的逻辑,然后调用父类Show方法。最后我们在Main方法 声明两个技能条名称( 恶魔猎手和剑圣) 然后分别把属于他们各自的技能声明好,然后就像叠罗汉一个把他们拼接起来。  

   

      可以看到,输出的效果就是我们按照的装饰顺序输出的。看完这里是不是觉得Decorator装饰模式特别简单却又特别好用呢,OK,我们再来回顾下Decorator装饰模式的一些要点和注意事项。

  通过采用组合,而非继承的手法,Decorator装饰模式实现了在运动时动态地扩展对象功能的能力,而且可以根据需求扩展多个功能,避免了单独使用继承带来的"灵活性差"和"多子类衍生问题"。
  Component类在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为,而且Decorator类对于Component类应该透明--换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。
  Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的借口,但在实现上又表现为 has-a component的组合关系,即Decorator类又使用了另外一个Component类,我们可以使用一个或者多个Decorator对象来装饰一个component对象,且装饰后的对象仍然是一个component对象。
 Decorator装饰模式并非解决"多子类衍生的多继承"问题,Decorator装饰模式应用的要点在于解决"主体类在多个方向上的扩展功能"--是为装饰的含义。
  总的来说,Decorator装饰模式可以动态的给一个对象增加一些额外的职责,就增加功能而言,Decorator装饰模式比生产子类更为灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值