GoF之装饰模式遇见王者荣耀、刺激战场

装饰(Decorator Pattern)模式

在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。就增加功能来说,装饰模式比生成子类更为灵活。

使用场景:

  1. 需要扩展一个类的功能,或给一个类添加附加职责。

  2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

  3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

4.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

优点:

1.Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

  1. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:

  1. 这种比继承更加灵活机动的特性,同时也更加复杂。

  2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

3.装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

具体实现:

王者荣耀英雄角色安琪拉,学三个技能,1(Q)、2(W)、3(E)的动态实现。

//Component 英雄接口 
publicinterface Hero {
 //学习技能
 void learnSkills();
}
//ConcreteComponent具体英雄安琪拉,这里可以用新的英雄实现类来增加新英雄角色
public class Angela implements Hero {
 private String name;
 public Angela(Stringname) {
 this.name = name;
 }
 @Override
 public void learnSkills() {
 System.out.println(name + "学习了以上技能!");
 }
}
 //Decorator 技能池 通过增加英雄实现类,可以增加英雄技能池、皮肤池、武器池等待
 public abstractSkills implements Hero{
 //持有一个英雄对象接口
 private Hero hero;
 public Skills(Herohero) {
 this.hero = hero;
 }
 @Override
 public void learnSkills() {
 if(hero != null)
 hero.learnSkills();
 } 
}
//ConreteDecorator技能:Q 通过增加技能实现类即可增加技能种类
public class Skill_Q extends Skills{
 private String skillName;
 public Skill_Q(Hero hero,String skillName) {
 super(hero);
 this.skillName = skillName;
 }
 @Override
 public voidlearnSkills() {
 System.out.println("学习技能Q:"+skillName);
 super.learnSkills();
 }
}
 //ConreteDecorator 技能:W
 public class Skill_W extends Skills{
 private String skillName;
 public Skill_W(Hero hero,String skillName) {
 super(hero);
 this.skillName = skillName;
 }
 @Override
 public voidlearnSkills() {
 System.out.println("学习技能W:"+ skillName);
 super.learnSkills();
 }
 }
 //ConreteDecorator 技能:E
 public class Skill_E extends Skills{
 private String skillName;
 public Skill_E(Hero hero,StringskillName) {
 super(hero);
 this.skillName =skillName;
 }
 @Override
 public voidlearnSkills() {
 System.out.println("学习技能E:"+skillName);
 super.learnSkills();
 }
 }
 //客户端:召唤师 
 public class Player {
 public static void main(String[]args) {
 //选择英雄 有多少英雄接口实现类 就有多少种选择
 Hero hero = newAngela("安琪拉");
 Skills skills = new Skills(hero);
 //装扮的顺序不限 此为单独学习技能
 Skills q = new Skill_Q(skills,"火球术");
 Skillsw = new Skill_W(skills,"混沌火种");
 Skillse = new Skill_E(skills,"制热光辉");
 //学习技能
 q.learnSkills();
 w.learnSkills();
 e.learnSkills();
 //一整套技能学习
 Skills q = newSkill_Q(skills,"火球术");
 Skills w = newSkill_W(q,"混沌火种");
 Skills e = newSkill_E(w,"制热光辉");
 e.learnSkills();
 }
}

《刺激战场》游戏里面装备98K枪械,更换弹夹、倍镜。
Kar 98K有5发子弹;

装上弹匣后有10发子弹;

装上4倍镜后可以进行4倍瞄准;

装上8倍镜后可以进行4倍瞄准、8倍瞄准。

//定义具备射击功能的枪械接口
public interface Gun {
 //射击
 publicvoid fire();
}
//创建具体的枪械实现类Kar98K,默认5发子弹
public class Kar98K implements Gun {
 @Override
 publicvoid fire() {
 System.out.println("射击5次");
 }
}
//对枪械的弹夹进行装饰,抽象实现枪械接口
public abstract class AbstractMagazine implements Gun{
//持有枪械对象
 private Gun gun;
 public AbstractMagazine(Gun gun) {
 this.gun = gun;
 }
 @Override
 public void fire() {
 gun.fire();
 }
}
//枪械弹夹装饰的具体实现类,子弹增加至10发
public class Magazine extends AbstractMagazine {
 public Magazine(Gun gun) {
 super(gun);
 }
 @Override
 public void fire() {
 System.out.println("射击10次");
 }
}
//客户端
public class Player {
 public static void main(String[] args) {
 //捡起一把98K
 Gun gun = newKar98K();
 //射击5次
 gun.fire();
 //装饰上弹匣
 gun = new Magazine(gun);
 //射击10次
 gun.fire();
 }
 }

现在我要装上4倍镜,使它具有4倍瞄准功能,这是枪支原本没有的功能。

扩展枪支接口功能:

//对枪械接口的继承,再增加倍镜装饰
public interface Aim4X extends Gun {
 public void aim4X();
}
public abstract class AbstractTelescope4X implements Aim4X {
 private Gun gun;
 public AbstractTelescope4X(Gun gun) {
 this.gun = gun;
 }
 @Override
 public void fire() {
 gun.fire();
 }
}
public class Telescope4X extends AbstractTelescope4X {
 public Telescope4X(Gun gun) {
 super(gun);
 }
 @Override
 publicvoid aim4X() {
 System.out.println("已进入4倍瞄准模式");
 }
}
//55式4倍镜
public class Telescope4X55 extends AbstractTelescope4X {
 public Telescope4X55(Gun gun) {
 super(gun);
 }
 @Override
 publicvoid aim4X() {
 System.out.println("4倍超级瞄准已部署");
 }
 }
 
public class Player {
 public static void main(String[] args) {
 //捡起一把98K
 Gun gun = newKar98K();
 //装饰上4倍镜
 Aim4X aim4X = new Telescope4X(gun);
 //4倍瞄准]
 aim4X.aim4X();
 //射击
 aim4X.fire();
 //先装饰上弹匣
 gun = new Magazine(gun);
 //再装饰上4倍镜
 aim4X = new Telescope4X(gun);
 //4倍瞄准
 aim4X.aim4X();
 //换上55式4倍镜
 aim4X = new Telescope4X55(gun);
 //射击!
 aim4X.fire();
 }
 }

现在我要装上8倍镜,它具有4倍瞄准功能,也具有8倍瞄准功能。

扩展接口:

public interface Aim8X extends Aim4X {
 public void aim8X();
 }
public abstract class AbstractTelescope8X implements Aim8X {
 private Gun gun;
 public AbstractTelescope8X(Gun gun) {
 this.gun = gun;
 }
 @Override
 public void fire() {
 gun.fire();
 }
 }
public class Telescope8X extends AbstractTelescope8X {
 public Telescope8X(Gun gun) {
 super(gun);
 }
 @Override
 publicvoid aim8X() {
 System.out.println("进入8倍瞄准模式");
 }
 @Override
 publicvoid aim4X() {
 System.out.println("进入4倍瞄准模式");
 }
}
 
public class Player {
 public static void main(String[] args) {
 //先装饰上弹匣
 gun = new Magazine(gun);
 //再装饰上8倍镜
 aim8X = new Telescope8X(gun);
 //8倍瞄准
 aim8X.aim8X();
 //敌人很近,换4倍
 aim8X.aim4X();
 //射击!
 aim8X.fire();
 }
 }

原文:https://mp.weixin.qq.com/s/hxxNd2QJwKdOecLiDmJCcA

作者:专注一行代码

来源:微信公众号

免费分享java技术资料,需要的朋友可以在关注后私信我

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值