zoukankan      html  css  js  c++  java
  • 装饰器(Decorator)模式

    1  装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。通常给对象添加功能,要么直接修改对象添加相应的功能,要么派生对应的子类来扩展,抑或是使用对象组合的方式。显然,直接修改对应的类这种方式并不可取。在面向对象的设计中,而我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式,可以很灵活的给对象添加所需要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。总之,装饰模式是通过把复杂的功能简单化,分散化,然后再运行期间,根据需要来动态组合的这样一个模式。
    2  问题提出:在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?
    这时我们就可以使用装饰器模式
    同样的我们还是来举个例子看看:

    设计一个小游戏 游戏中很多的角色(角色包括: 枪手Gunmen,刀客swordsman等), 角色拥有武器,武器包括(刀knife(150),枪gun(200),棍(100)),

    游戏中我们可以通过给武器加上一些宝石(蓝宝石,红宝石,绿宝石) 来加强武器的攻击力。

    红宝石每增加一颗 攻击力 +5;ruby

    蓝宝石每增加一颗 攻击力+10;sapphire

    绿宝石每增加一颗 攻击力 +20

    结构图:

     首先还是先创建两个接口;

    1 package ooad.design.Decorator;
    2 
    3 public interface IWeapon {
    4   public String getName();
    5   public int getAttack();
    6 }
    1 package ooad.design.Decorator;
    2 
    3 public interface IRole {
    4      public void attack(IWeapon weapon);
    5 
    6 }

    接着我们创建武器:

     1 package ooad.design.Decorator;
     2 
     3 public class Gun implements IWeapon {
     4     private String name;
     5     
     6 
     7     public Gun(String name) {
     8         super();
     9         this.name = name;
    10     }
    11 
    12     @Override
    13     public String getName() {
    14         
    15         return this.name;
    16     }
    17 
    18     @Override
    19     public int getAttack() {
    20         
    21         return 200;
    22     }
    23 
    24     
    25 
    26 }

     然后我们创建角色:

     1 package ooad.design.Decorator;
     2 
     3 public class Gunmen implements IRole {
     4     private String name;
     5     
     6 
     7     public Gunmen(String name) {
     8         super();
     9         this.name = name;
    10     }
    11     public String getName() {
    12         return name;
    13     }
    14 
    15 
    16     public void setName(String name) {
    17         this.name = name;
    18     }
    19 
    20 
    21     @Override
    22     public void attack(IWeapon weapon) {
    23        System.out.println(this.name+"使用"+weapon.getName()+"进行攻击,造成的伤害值为:"+weapon.getAttack());    
    24     }
    25 
    26 }

    因为武器需要宝石来装饰,所以呢我们创建一个装饰的抽象类

    1 package ooad.design.Decorator;
    2 
    3 public abstract class Decorator implements IWeapon{
    4     public abstract int getAttack();
    5 
    6 }

    宝石类:

     1 package ooad.design.Decorator;
     2 
     3 public class Ruby extends Decorator {
     4     private IWeapon weapon;
     5        
     6     public Ruby(IWeapon weapon) {
     7         super();
     8         this.weapon = weapon;
     9     }
    10 
    11     @Override
    12     public String getName() {
    13         
    14         return "增加了红宝石的"+weapon.getName();
    15     }
    16 
    17     @Override
    18     public int getAttack() {
    19         
    20         return 5+weapon.getAttack();
    21     }
    22 
    23 }

     来个测试:

     1 package ooad.design.Decorator;
     2 
     3 public class Test {
     4 
     5     public static void main(String[] args) {
     6         IRole r =new Gunmen("枪手");
     7         IWeapon w=new Gun("火箭枪");
     8         r.attack(w);
     9         w=new Ruby(w);
    10         r.attack(w);
    11     }
    12 
    13 }

     最终结果:

    枪手使用火箭枪进行攻击,造成的伤害值为:200
    枪手使用增加了红宝石的火箭枪进行攻击,造成的伤害值为:205

    如果想要用两颗红宝石我们就可以这样:

    r.attack(w);

    r.attack(w);

    结果呢则是:

    枪手使用火箭枪进行攻击,造成的伤害值为:200
    枪手使用增加了红宝石的增加了红宝石的火箭枪进行攻击,造成的伤害值为:210

    增加了红宝石的增加了红宝石的  这样看起来不舒服吧,该怎样去判断他到底增加了几颗宝石,我们就显示几颗宝石呢?

    例子中的角色,武器,装饰的宝石,我就没有全部写出来了!

  • 相关阅读:
    软件质量见解
    Vim 简明教程【转载】
    Actor Mailbox
    Unity对齐工具
    静态AOP Fody PropertyChanged
    棋牌分布式架构
    死锁
    curl 获取自定义数据
    WPF RichTextBox添加一条有颜色的记录
    arp -s 添加失败:拒绝访问
  • 原文地址:https://www.cnblogs.com/hellokitty1/p/4654127.html
Copyright © 2011-2022 走看看