目录java
Decorator(装饰器)模式属于结构型模式。
好比当其须要三种不一样的附加特性,能够为其建立三个派生类。可是若它还须要同时具备其中两种特性或者是各类特性的任意组合的时候,类继承的方法就再也不适合了。
它容许向一个现有的对象不经过继承来添加新的功能,同时又不改变其结构。git
前一阵子张家辉代言的《贪玩蓝月》广告火了,“我系喳喳辉,是兄弟就来砍我~”被洗脑到如今,正好用这个游戏来解释一下装饰器模式。github
玩游戏的人都知道这种类传奇的游戏核心玩法就是买装备,打怪,升级,买装备这样反复。设计模式
刚注册帐号进入游戏的玩家假设只有一条大裤衩,价值5金币,随着刷怪升级,身上的装备也在一件件增多,这时候咱们须要知道身上的装备价值多少金币。ide
定义玩家组件化
public interface Gamer { /** * 获取目前的装备 * @return */ String getEquip(); /** * 获取目前身上装备的价格 * @return */ int getPrice(); }
定义具体的法师职业玩家ui
public class MasterGamer implements Gamer { /** * 获取目前的装备 * * @return */ @Override public String getEquip() { return "大裤衩"; } /** * 获取目前身上装备的价格 * * @return */ @Override public int getPrice() { return 5; } }
新法师玩家出门只有大裤衩,装备全靠打。this
装备“法师权杖”设计
public class TruncheonMasterGamer extends MasterGamer{ /** * 获取目前的装备 * * @return */ @Override public String getEquip() { return super.getEquip()+",法师权杖"; } /** * 获取目前身上装备的价格 * * @return */ @Override public int getPrice() { return super.getPrice()+50; } }
继续装备“魔法斗篷”code
public class CloakTruncheonMasterGamer extends TruncheonMasterGamer{ /** * 获取目前的装备 * * @return */ @Override public String getEquip() { return super.getEquip()+",魔法斗篷"; } /** * 获取目前身上装备的价格 * * @return */ @Override public int getPrice() { return super.getPrice()+80; } }
注意,这里是在以前已经装备了“法师权杖”之上去继承。
计算装备价格
CloakTruncheonMasterGamer gamer = new CloakTruncheonMasterGamer(); System.out.println("当前装备:"+gamer.getEquip()+"\n装备总价值:"+gamer.getPrice());
输出结果
当前装备:大裤衩,法师权杖,魔法斗篷 装备总价值:135
声明通用装饰器基类“装备”
public abstract class Equip implements Gamer { private Gamer gamer; public Equip(Gamer gamer) { this.gamer = gamer; } /** * 获取目前的装备 * * @return */ @Override public String getEquip() { return gamer.getEquip(); } /** * 获取目前身上装备的价格 * * @return */ @Override public int getPrice() { return gamer.getPrice(); } }
具体装饰器“法师权杖”
public class Truncheon extends Equip { public Truncheon(Gamer gamer) { super(gamer); } /** * 获取目前的装备 * * @return */ @Override public String getEquip() { return super.getEquip()+",法师权杖"; } /** * 获取目前身上装备的价格 * * @return */ @Override public int getPrice() { return super.getPrice()+50; } }
具体装饰器“魔法斗篷”
public class Cloak extends Equip { public Cloak(Gamer gamer) { super(gamer); } /** * 获取目前的装备 * * @return */ @Override public String getEquip() { return super.getEquip()+",魔法斗篷"; } /** * 获取目前身上装备的价格 * * @return */ @Override public int getPrice() { return super.getPrice()+80; } }
计算装备价格
//建立一个法师玩家 Gamer gamer = new MasterGamer(); //给法师玩家装备法师权杖 gamer = new Truncheon(gamer); //给法师玩家装备魔法斗篷 gamer = new Cloak(gamer); System.out.println("当前装备:"+gamer.getEquip()+"\n装备总价值:"+gamer.getPrice());
输出结果
当前装备:大裤衩,法师权杖,魔法斗篷 装备总价值:135
上面例子比较简单,传统继承实现和装饰器模式实现区别不是很明显,但仔细思考仍是会发现一些区别:
这种设计模式下不只能够扩展一个类的功能,也能够动态增长功能,动态撤销。但缺点就是多层装饰使用起来相对比较复杂。本质是将具体功能职责划分(例如区分核心组件以及附加属性职责)减小子类直接继承父类的耦合性。
你能够在这里获取相关代码:设计模式-Decorator模式