11,装饰模式-孙悟空的六神装
2017-11-03 15:37
197 查看
一,前言
7种结构型设计模式:桥接模式,适配器模式,装饰模式,组合模式,享元模式,外观模式,代理模式 上篇我们说了外观模式:提供一个统一接口来访问子系统中的一群接口 外观定义了一个高层接口,让子系统更容易使用 开发中我们为一个对象添加新行为通常会采用继承的方式 但通常这样做会导致子类泛滥的结果也就是我们常说的类爆炸,为后续的维护带来不便 本着"开放-关闭"的设计原则,我们希望在不修改原有代码的情况下,为对象赋予新的职责 这篇的结构型设计模式就可以做到,它就是装饰模式,也叫做装饰器或装饰者模式
二,装饰模式简介
1,简介:装饰者模式:动态地将责任附加到对象上,在不修改任何底层代码的情况下,为对象赋予新的职责
2,装饰模式类图:
从类图中我们可以看到: 装饰者和被装饰者(组件)拥有相同的接口,所以装饰者能够取代被装饰者 装饰者与组件进行组合时,通过对象组合为组件加入新的行为 所以装饰者模式能在不创建更多子类的情况下,实现对象功能的拓展 这也正是组合的威力所在,多用组合少用继承 如果依赖继承,类的行为只能在编译时静态决定,行为来自超类或子类进行覆盖 组合可以把装饰器和组件进行混合,而且是在运行时才决定具体行为
3,装饰模式中的角色:
抽象组件(Component)角色:给出一个抽象接口,规范准备接收附加责任的对象。 具体组件(ConcreteComponent)角色:定义一个将要接收附加责任的类。 装饰(Decorator)角色:持有一个组件对象(Component)的实例,并定义一个与抽象构件接口一致的接口。 具体装饰(ConcreteDecorator)角色:负责为组件对象赋予新职责。
三,装饰模式场景
我们选取一个比较适合装饰模式的场景来对这个模式进行学习 最后我选择了游戏中为角色添加装备来获得属性加成的例子 那么这篇的主题又回到了大家感兴趣的游戏话题上 我们就来看看"王者荣耀"中孙悟空这个英雄的六神装 ps:这里对英雄和装备属性做了修改,和真实游戏中的属性不一致,望谅解!
我们的场景是这样的: 1,创建一个抽象组件Hero(即抽象组件角色),通过继承此类创建具体英雄,此类定义了英雄属性 2,通过继承Hero类创建具体英雄(孙悟空),并针对英雄个性化做属性调整 3,创建一个抽象装备类Equipment(即抽象装饰角色),继承自组件Hero,通过继承此类创建具体装备,此类需定义装饰新功能的接口,以重写为新的功能供外部调用 4,通过继承Equipment类创建具体装备类,此类需持有一个具体英雄(Hero)的引用,重写接口时对此引用信息做修改,以实现功能的变更和添加 5,使用4的方式创建6件装备,并逐一为英雄装饰,打印日志查看装饰后的英雄属性
四,装饰模式例子
1,创建抽象组件Hero,即抽象组件角色,定义英雄属性package com.brave.decorator.pesticide.hero; /** * 抽象英雄 * -每个具体英雄都继承自此类 * -默认属性数值均为100暴击率0%暴击效果2倍 * * @author Brave * */ public abstract class Hero { private String name = ""; // 名称 private double HP = 100; // 生命值 private double MP = 100; // 魔法值 private double ATK = 100; // 攻击力 private double DEF = 100; // 防御力 private double CRT = 0; // 暴击率加成 private double CRTE = 2; // 暴击效果 private double MS = 0; // 移动速度加成 private double AB = 0; // 破甲加成 private String equipment = ""; // 装备 public String getName() { return name; } public void setName(String name) { this.name = name; } public double getHP() { return HP; } public void setHP(double hP) { HP = hP; } public double getMP() { return MP; } public void setMP(double mP) { MP = mP; } public double getATK() { return ATK; } public void setATK(double aTK) { ATK = aTK; } public double getDEF() { return DEF; } public void setDEF(double dEF) { DEF = dEF; } public double getCRT() { return CRT; } public void setCRT(double cRT) { CRT = cRT; } public double getCRTE() { return CRTE; } public void setCRTE(double cRTE) { CRTE = cRTE; } public double getMS() { return MS; } public void setMS(double mS) { MS = mS; } public String getEquipment() { return equipment; } public void setEquipment(String equipment) { this.equipment = equipment; } public double getAB() { return AB; } public void setAB(double aB) { AB = aB; } public void printHeroAttr() { System.out.println("name = " + name); System.out.println("生命值:HP = " + HP); System.out.println("魔法值:MP = " + MP); System.out.println("攻击力:ATK = " + ATK); System.out.println("防御力:DEF = " + DEF); System.out.println("暴击率加成:CRT = " + CRT); System.out.println("暴击效果:CRTE = " + CRTE); System.out.println("移动速度加成:MS = " + MS); if(!equipment.equals(""))System.out.println("装备:equipment = " + equipment); } }
2,通过继承Hero类创建具体英雄孙悟空,针对英雄个性化做属性调整
package com.brave.decorator.pesticide.hero; /** * 具体英雄-孙悟空 * 初始暴击率为20%,暴击伤害150%; * * @author Brave * */ public class MonkeyKing extends Hero { public MonkeyKing() { setName("孙悟空"); setCRT(0.2); setCRTE(1.5); } }
3,继承自组件Hero,创建抽象装备类Equipment,定义装饰新功能的接口,以重写为新的功能供外部调用
package com.brave.decorator.pesticide.equipment; import com.brave.decorator.pesticide.hero.Hero; /** * 抽象装备 * -每个具体装备都继承自此类 * * @author Brave * */ public abstract class Equipment extends Hero{ // 强制重写-装备名称 public abstract String getName(); // 输出准备此件装备后的所有装备信息 public abstract double getHP(); public abstract double getMP(); public abstract double getATK(); public abstract double getDEF(); public abstract double getCRT(); public abstract double getCRTE(); public abstract double getMS(); public abstract double getAB(); public abstract String getEquipment(); // 强制重写-输出装备此件装备后的全部属性 public abstract void printHeroAttr(); }
4,通过继承Equipment类创建具体装备类
此类持有一个具体英雄(Hero)的引用,重写接口时对此引用信息做修改,以实现功能的变更和添加
创建6件装备: 鞋子:100移速 无尽之刃:50%暴击+50%暴击效果 破甲弓:100攻击+100破甲 冰痕之握:100防御+100魔法 装饰泣血之刃:100攻击+100生命 破军:200攻击
1)鞋子:增加100点移动速度
package com.brave.decorator.pesticide.equipment; import com.brave.decorator.pesticide.hero.Hero; /** * 鞋子:增加100点移动速度 * @author Brave * */ public class Shoes extends Equipment { private Hero hero; public Shoes(Hero hero) { this.hero = hero; } @Override public void printHeroAttr() { System.out.println("name = " + getName()); System.out.println("生命值:HP = " + getHP()); System.out.println("魔法值:MP = " + getMP()); System.out.println("攻击力:ATK = " + getATK()); System.out.println("防御力:DEF = " + getDEF()); System.out.println("暴击率加成:CRT = " + getCRT()); System.out.println("暴击效果:CRTE = " + getCRTE()); System.out.println("移动速度加成:MS = " + getMS()); System.out.println("破甲加成:AB = " + getAB()); System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment()); } @Override public String getName() { return "鞋子"; } @Override public double getHP() { return hero.getHP(); } @Override public double getMP() { return hero.getMP(); } @Override public double getATK() { return hero.getATK(); } @Override public double getDEF() { return hero.getDEF(); } @Override public double getCRT() { return hero.getCRT(); } @Override public double getCRTE() { return hero.getCRTE(); } @Override public double getMS() { return hero.getMS() + 100; } @Override public String getEquipment() { return hero.getEquipment() + getName() + ","; } @Override public double getAB() { return hero.getAB(); } }
2)无尽之刃:50%暴击+50%暴击效果
package com.brave.decorator.pesticide.equipment; import com.brave.decorator.pesticide.hero.Hero; /** * 无尽之刃:增加暴击率50%.暴击效果50% * @author Brave * */ public class InfinitySword extends Equipment { private Hero hero; public InfinitySword(Hero hero) { this.hero = hero; } @Override public void printHeroAttr() { System.out.println("name = " + getName()); System.out.println("生命值:HP = " + getHP()); System.out.println("魔法值:MP = " + getMP()); System.out.println("攻击力:ATK = " + getATK()); System.out.println("防御力:DEF = " + getDEF()); System.out.println("暴击率加成:CRT = " + getCRT()); System.out.println("暴击效果:CRTE = " + getCRTE()); System.out.println("移动速度加成:MS = " + getMS()); System.out.println("破甲加成:AB = " + getAB()); System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment()); } @Override public String getName() { return "无尽之刃"; } @Override public double getHP() { return hero.getHP(); } @Override public double getMP() { return hero.getMP(); } @Override public double getATK() { return hero.getATK(); } @Override public double getDEF() { return hero.getDEF(); } @Override public double getCRT() { return hero.getCRT() + 0.5; } @Override public double getCRTE() { return hero.getCRTE() + 0.5; } @Override public double getMS() { return hero.getMS(); } @Override public String getEquipment() { return hero.getEquipment() + getName() + ","; } @Override public double getAB() { return hero.getAB(); } }
3)破甲弓:100攻击+100破甲
package com.brave.decorator.pesticide.equipment; import com.brave.decorator.pesticide.hero.Hero; /** * 破甲弓:100攻击+100破甲 * @author Brave * */ public class ArmorBow extends Equipment { private Hero hero; public ArmorBow(Hero hero) { this.hero = hero; } @Override public void printHeroAttr() { System.out.println("name = " + getName()); System.out.println("生命值:HP = " + getHP()); System.out.println("魔法值:MP = " + getMP()); System.out.println("攻击力:ATK = " + getATK()); System.out.println("防御力:DEF = " + getDEF()); System.out.println("暴击率加成:CRT = " + getCRT()); System.out.println("暴击效果:CRTE = " + getCRTE()); System.out.println("移动速度加成:MS = " + getMS()); System.out.println("破甲加成:AB = " + getAB()); System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment()); } @Override public String getName() { return "破甲弓"; } @Override public double getHP() { return hero.getHP(); } @Override public double getMP() { return hero.getMP(); } @Override public double getATK() { return hero.getATK() + 100; } @Override public double getDEF() { return hero.getDEF(); } @Override public double getCRT() { return hero.getCRT(); } @Override public double getCRTE() { return hero.getCRTE(); } @Override public double getMS() { return hero.getMS(); } @Override public String getEquipment() { return hero.getEquipment() + getName() + ","; } @Override public double getAB() { return hero.getAB() + 100; } }
4)冰痕之握:100防御+100魔法
package com.brave.decorator.pesticide.equipment; import com.brave.decorator.pesticide.hero.Hero; /** * 复活甲:100防御+100魔法值 * @author Brave * */ public class IceMarkGrip extends Equipment { private Hero hero; public IceMarkGrip(Hero hero) { this.hero = hero; } @Override public void printHeroAttr() { System.out.println("name = " + getName()); System.out.println("生命值:HP = " + getHP()); System.out.println("魔法值:MP = " + getMP()); System.out.println("攻击力:ATK = " + getATK()); System.out.println("防御力:DEF = " + getDEF()); System.out.println("暴击率加成:CRT = " + getCRT()); System.out.println("暴击效果:CRTE = " + getCRTE()); System.out.println("移动速度加成:MS = " + getMS()); System.out.println("破甲加成:AB = " + getAB()); System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment()); } @Override public String getName() { return "冰痕之握"; } @Override public double getHP() { return hero.getHP(); } @Override public double getMP() { return hero.getMP() + 100; } @Override public double getATK() { return hero.getATK(); } @Override public double getDEF() { return hero.getDEF() + 100; } @Override public double getCRT() { return hero.getCRT(); } @Override public double getCRTE() { return hero.getCRTE(); } @Override public double getMS() { return hero.getMS(); } @Override public String getEquipment() { return hero.getEquipment() + getName() + ","; } @Override public double getAB() { return hero.getAB(); } }
5)泣血之刃:100攻击+100生命
package com.brave.decorator.pesticide.equipment; import com.brave.decorator.pesticide.hero.Hero; /** * 泣血之刃:100攻击+100生命值 * @author Brave * */ public class BloodSword extends Equipment { private Hero hero; public BloodSword(Hero hero) { this.hero = hero; } @Override public void printHeroAttr() { System.out.println("name = " + getName()); System.out.println("生命值:HP = " + getHP()); System.out.println("魔法值:MP = " + getMP()); System.out.println("攻击力:ATK = " + getATK()); System.out.println("防御力:DEF = " + getDEF()); System.out.println("暴击率加成:CRT = " + getCRT()); System.out.println("暴击效果:CRTE = " + getCRTE()); System.out.println("移动速度加成:MS = " + getMS()); System.out.println("破甲加成:AB = " + getAB()); System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment()); } @Override public String getName() { return "泣血之刃"; } @Override public double getHP() { return hero.getHP() + 100; } @Override public double getMP() { return hero.getMP(); } @Override public double getATK() { return hero.getATK() + 100; } @Override public double getDEF() { return hero.getDEF(); } @Override public double getCRT() { return hero.getCRT(); } @Override public double getCRTE() { return hero.getCRTE(); } @Override public double getMS() { return hero.getMS(); } @Override public String getEquipment() { return hero.getEquipment() + getName() + ","; } @Override public double getAB() { return hero.getAB(); } }
6)破军:200攻击
package com.brave.decorator.pesticide.equipment; import com.brave.decorator.pesticide.hero.Hero; /** * 破军:200攻击 * @author Brave * */ public class Breach extends Equipment { private Hero hero; public Breach(Hero hero) { this.hero = hero; } @Override public void printHeroAttr() { System.out.println("name = " + getName()); System.out.println("生命值:HP = " + getHP()); System.out.println("魔法值:MP = " + getMP()); System.out.println("攻击力:ATK = " + getATK()); System.out.println("防御力:DEF = " + getDEF()); System.out.println("暴击率加成:CRT = " + getCRT()); System.out.println("暴击效果:CRTE = " + getCRTE()); System.out.println("移动速度加成:MS = " + getMS()); System.out.println("破甲加成:AB = " + getAB()); System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment()); } @Override public String getName() { return "破甲弓"; } @Override public double getHP() { return hero.getHP(); } @Override public double getMP() { return hero.getMP(); } @Override public double getATK() { return hero.getATK() + 200; } @Override public double getDEF() { return hero.getDEF(); } @Override public double getCRT() { return hero.getCRT(); } @Override public double getCRTE() { return hero.getCRTE(); } @Override public double getMS() { return hero.getMS(); } @Override public String getEquipment() { return hero.getEquipment() + getName() + ","; } @Override public double getAB() { return hero.getAB(); } }
5,测试装饰模式,逐一为英雄装饰6件装备,打印日志查看装饰后的英雄属性
package com.brave.decorator.pesticide; import com.brave.decorator.pesticide.equipment.ArmorBow; import com.brave.decorator.pesticide.equipment.BloodSword; import com.brave.decorator.pesticide.equipment.Breach; import com.brave.decorator.pesticide.equipment.IceMarkGrip; import com.brave.decorator.pesticide.equipment.InfinitySword; import com.brave.decorator.pesticide.equipment.Shoes; import com.brave.decorator.pesticide.hero.Hero; import com.brave.decorator.pesticide.hero.MonkeyKing; /** * 测试装饰模式 * * 在不修改任何底层代码的情况下.为对象赋予新的职责 * 装饰者模式:动态地将责任附加到对象上,若要拓展功能,装饰者提供了比继承更有弹性的替代方案 * * @author Brave * */ public class Client { public static void main(String[] args) { System.out.println("*****************初始化英雄******************"); Hero hero = new MonkeyKing(); hero.printHeroAttr(); System.out.println("*****************装饰鞋子:100移速******************"); Hero shoes = new Shoes(hero); shoes.printHeroAttr(); System.out.println("*****************装饰无尽之刃:50%暴击+50%暴击效果******************"); Hero infinitySword = new InfinitySword(shoes); infinitySword.printHeroAttr(); System.out.println("*****************装饰破甲弓:100攻击+100破甲******************"); Hero armorBow = new ArmorBow(infinitySword); armorBow.printHeroAttr(); System.out.println("*****************装饰冰痕之握:100防御+100魔法******************"); Hero iceMarkGrip = new IceMarkGrip(armorBow); iceMarkGrip.printHeroAttr(); System.out.println("*****************装饰泣血之刃:100攻击+100生命******************"); Hero bloodSword = new BloodSword(iceMarkGrip); bloodSword.printHeroAttr(); System.out.println("*****************装饰破军:200攻击******************"); Hero breach = new Breach(bloodSword); breach.printHeroAttr(); } }
6,打印日志输出,查看属性
*****************初始化英雄****************** name = 孙悟空 生命值:HP = 100.0 魔法值:MP = 100.0 攻击力:ATK = 100.0 防御力:DEF = 100.0 暴击率加成:CRT = 0.2 暴击效果:CRTE = 1.5 移动速度加成:MS = 0.0 *****************装饰鞋子:100移速****************** name = 鞋子 生命值:HP = 100.0 魔法值:MP = 100.0 攻击力:ATK = 100.0 防御力:DEF = 100.0 暴击率加成:CRT = 0.2 暴击效果:CRTE = 1.5 移动速度加成:MS = 100.0 破甲加成:AB = 0.0 装备:equipment = 鞋子, *****************装饰无尽之刃:50%暴击+50%暴击效果****************** name = 无尽之刃 生命值:HP = 100.0 魔法值:MP = 100.0 攻击力:ATK = 100.0 防御力:DEF = 100.0 暴击率加成:CRT = 0.7 暴击效果:CRTE = 2.0 移动速度加成:MS = 100.0 破甲加成:AB = 0.0 装备:equipment = 鞋子,无尽之刃, *****************装饰破甲弓:100攻击+100破甲****************** name = 破甲弓 生命值:HP = 100.0 魔法值:MP = 100.0 攻击力:ATK = 200.0 防御力:DEF = 100.0 暴击率加成:CRT = 0.7 暴击效果:CRTE = 2.0 移动速度加成:MS = 100.0 破甲加成:AB = 100.0 装备:equipment = 鞋子,无尽之刃,破甲弓, *****************装饰冰痕之握:100防御+100魔法****************** name = 冰痕之握 生命值:HP = 100.0 魔法值:MP = 200.0 攻击力:ATK = 200.0 防御力:DEF = 200.0 暴击率加成:CRT = 0.7 暴击效果:CRTE = 2.0 移动速度加成:MS = 100.0 破甲加成:AB = 100.0 装备:equipment = 鞋子,无尽之刃,破甲弓,冰痕之握, *****************装饰泣血之刃:100攻击+100生命****************** name = 泣血之刃 生命值:HP = 200.0 魔法值:MP = 200.0 攻击力:ATK = 300.0 防御力:DEF = 200.0 暴击率加成:CRT = 0.7 暴击效果:CRTE = 2.0 移动速度加成:MS = 100.0 破甲加成:AB = 100.0 装备:equipment = 鞋子,无尽之刃,破甲弓,冰痕之握,泣血之刃, *****************装饰破军:200攻击****************** name = 破甲弓 生命值:HP = 200.0 魔法值:MP = 200.0 攻击力:ATK = 500.0 防御力:DEF = 200.0 暴击率加成:CRT = 0.7 暴击效果:CRTE = 2.0 移动速度加成:MS = 100.0 破甲加成:AB = 100.0 装备:equipment = 鞋子,无尽之刃,破甲弓,冰痕之握,泣血之刃,破甲弓,
四,装饰模式的优点与缺点
装饰模式的优点: 1,装饰模式与继承的目的都是扩展对象功能,但装饰模式比继承更加灵活性。 装饰模式允许系统动态决定添加装饰,或移除装饰 继承关系是静态的,在系统运行前决定 2,可以灵活的"改造"对象,使用不同装饰器或改变排列组合顺序,实现多种组合 装饰模式的缺点: 装饰模式使用组合实现新功能的添加,相比继承的实现使用了较少的类 但由于装饰模式的特性,会产生比使用继承关系更多的对象 而这些对象都很相似,数量也较多,所以加大了系统错误的排查难度
模式到这里就简单的说完了,先备注一些后面要加入的部分
java中使用的装饰模式-IO
装饰模式和其他模式的区别,例如和适配器
相关文章推荐
- 11. 装饰器模式
- 设计模式C++实现(11)——装饰模式
- 设计模式(11)--装饰器模式
- 设计模式C++实现(11)——装饰模式
- (11)装饰模式
- 设计模式之11装饰模式(笔记)
- 设计模式C++实现(11)——装饰模式
- 设计模式C++实现(11)——装饰模式
- 设计模式C++实现(11)——装饰模式
- 11对缓冲流分析出来的设计模式--装饰设计模式
- 设计模式C++实现(11)——装饰模式
- 设计模式11-装饰模式
- 11-装饰模式
- 设计模式C++实现(11)——装饰模式
- 设计模式C++实现(11)——装饰模式
- 设计模式利剑11-装饰模式
- 设计模式C++实现(11)——装饰模式
- 设计模式C++实现(11)——装饰模式
- 设计模式C++实现(11)——装饰模式
- 设计模式C++实现(11)——装饰模式