今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义。

装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。

先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。这里还体现了一个原则:类应该对扩展开放,对修改关闭。

下面进入正题,今天在那看电影,忽然想起年轻时在游戏场上的血雨腥风啊,哈哈,下面以游戏为背景介绍装饰者模式。玩过游戏的兄弟应该都知道,游戏里面每个角色有武器、鞋子、护腕、戒指、还有各种红宝石、蓝宝石、黄宝石等等。

下面需求开始:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:

具体需求:

1、武器(攻击力20) 、戒指(攻击力5)、护腕(攻击力5)、鞋子(攻击力5)

2、蓝宝石(攻击力5/颗)、黄宝石(攻击力10/颗)、红宝石(攻击力15/颗)

3、每个装备可以随意镶嵌3颗

好了,需求介绍完毕,当然了,不要吐槽我的设计,尼玛鞋子哪来的攻击力,关键时刻也是可以砸人的嘛。下面开始初步的设想,出于多年面向对象的经验,我们可能会这么设计:

如果你这么设计了,我靠,就这么点需求你写了几百个类,随便添加两个宝石,哈哈,指数增长听过么,准备加班吧。

可能你还会这么设计:写一个超类,然后里面各种set宝石,然后在计算攻击力的地方,使劲的If有哪几种宝石,恭喜你,代码量不是很大,但是随便添加个武器,你得又多写多少个IF呢。

上面叙述了一些可能性的设计,都不是很好,下面看看如何将装饰者模式融入:

首先是装备的超类

package com.zhy.pattern.decorator;/*** 装备的接口* * @author zhy* */
public interface IEquip
{/*** 计算攻击力* * @return*/public int caculateAttack();/*** 装备的描述* * @return*/public String description();
}

然后分别是武器、戒指、护腕、鞋子

package com.zhy.pattern.decorator;/*** 武器* 攻击力20* @author zhy* */
public class ArmEquip implements IEquip
{@Overridepublic int caculateAttack(){return 20;}@Overridepublic String description(){return "屠龙刀";}}

package com.zhy.pattern.decorator;/*** 戒指* 攻击力 5* @author zhy**/
public class RingEquip implements IEquip
{@Overridepublic int caculateAttack(){return 5;}@Overridepublic String description(){return "圣战戒指";}}

package com.zhy.pattern.decorator;/*** 护腕* 攻击力 5* @author zhy**/
public class WristEquip implements IEquip
{@Overridepublic int caculateAttack(){return 5;}@Overridepublic String description(){return "圣战护腕";}}

package com.zhy.pattern.decorator;/*** 鞋子* 攻击力 5* @author zhy* */
public class ShoeEquip implements IEquip
{@Overridepublic int caculateAttack(){return 5;}@Overridepublic String description(){return "圣战靴子";}}

接下来当然是装饰品,宝石了,首先超类

package com.zhy.pattern.decorator;/*** 装饰品的接口* @author zhy**/
public interface IEquipDecorator extends IEquip
{}

下来蓝宝石、黄宝石、红宝石

package com.zhy.pattern.decorator;/*** 蓝宝石装饰品* 每颗攻击力+5* @author zhy* */
public class BlueGemDecorator implements IEquipDecorator
{/*** 每个装饰品维护一个装备*/private IEquip equip;public BlueGemDecorator(IEquip equip){this.equip = equip;}@Overridepublic int caculateAttack(){return 5 + equip.caculateAttack();}@Overridepublic String description(){return equip.description() + "+ 蓝宝石";}}

package com.zhy.pattern.decorator;/*** 黄宝石装饰品* 每颗攻击力+10* @author zhy* */
public class YellowGemDecorator implements IEquipDecorator
{/*** 每个装饰品维护一个装备*/private IEquip equip;public YellowGemDecorator(IEquip equip){this.equip = equip;}@Overridepublic int caculateAttack(){return 10 + equip.caculateAttack();}@Overridepublic String description(){return equip.description() + "+ 黄宝石";}}

package com.zhy.pattern.decorator;/*** 红宝石装饰品 每颗攻击力+15* * @author zhy* */
public class RedGemDecorator implements IEquipDecorator
{/*** 每个装饰品维护一个装备*/private IEquip equip;public RedGemDecorator(IEquip equip){this.equip = equip;}@Overridepublic int caculateAttack(){return 15 + equip.caculateAttack();}@Overridepublic String description(){return equip.description() + "+ 红宝石";}}

好了,到此结束,我们已经实现了需求的功能了,是不是每个类都很清晰加简单,下面看测试:

package com.zhy.pattern.decorator;public class Test
{public static void main(String[] args){// 一个镶嵌2颗红宝石,1颗蓝宝石的靴子System.out.println(" 一个镶嵌2颗红宝石,1颗蓝宝石的靴子");IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));System.out.println("攻击力  : " + equip.caculateAttack());System.out.println("描述 :" + equip.description());System.out.println("-------");// 一个镶嵌1颗红宝石,1颗蓝宝石的武器System.out.println(" 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器");equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));System.out.println("攻击力  : " + equip.caculateAttack());System.out.println("描述 :" + equip.description());System.out.println("-------");}
}

输出:

 一个镶嵌2颗红宝石,1颗蓝宝石的靴子
攻击力  : 40
描述 :圣战靴子+ 蓝宝石+ 红宝石+ 红宝石
-------一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器
攻击力  : 50
描述 :屠龙刀+ 黄宝石+ 蓝宝石+ 红宝石
-------

赞不赞,要是需求随便多几个装备,几种宝石,我们随随便便就可以加上,然后开开心心下班。

好了,恭喜你,你又学会了一个设计模式,装饰者模式。

现在根据例子对定义的理解,不用我多说吧。

Java的API中也有装饰者模式的身影,如果你初学Java,一定记得Java里面的各种流,很痛苦吧,但是当你明

白你们的设计之后就会感觉清晰很多。

把InputStream看作我们的IEquip,把FilterInputStream看作我们的IEquipDecorator,是不是和我们的设计几乎一样~

好了,就到这里,编程也是很有乐趣的么~是吧,各位看官留个言、给个赞呗~

源码点击下载

设计模式 装饰者模式 带你重回传奇世界相关推荐

  1. 7. 设计模式 装饰者模式 带你重回传奇世界

    今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义. 装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上. 先简单描述下装饰者模式发挥作用的地方,当我 ...

  2. Python设计模式-装饰器模式

    Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...

  3. [Head First设计模式]山西面馆中的设计模式——装饰者模式

    原文:[Head First设计模式]山西面馆中的设计模式--装饰者模式 引言 在山西面馆吃鸡蛋面的时候突然想起装饰者这个模式,觉得面馆这个场景跟书中的星巴兹咖啡的场景很像,边吃边思考装饰者模式.这里 ...

  4. 设计模式——装饰者模式

    本文是阅读 Head First 设计模式--装饰者模式的总结. 这本书的教学模式很不错,个人很喜欢,由实际的案例由浅入深,循序渐进的让你明白良好的设计是多么的优雅迷人(回头看看自己的代码,WTF!) ...

  5. 设计模式装饰者模式_装饰者模式如何拯救了我的一天

    设计模式装饰者模式 在工作中,我正在处理庞大的Java代码库,该代码库是由许多不同的开发人员在15年的时间里开发的. 并不是所有的事情都由书来完成,但是同时我通常无法重构遇到的每一个奇怪的事物. 尽管 ...

  6. 23种设计模式——装饰者模式

    文章目录 23种设计模式--装饰者模式 1.装饰者模式概述 2.装饰者模式的结构 3.装饰者模式的实现 4.装饰者模式的应用场景 23种设计模式--装饰者模式 1.装饰者模式概述 背景 有些人为了早上 ...

  7. 读书笔记---Head First 设计模式--- 装饰者模式

    读书笔记-Head First 设计模式- 装饰者模式 装饰者模式(Decorator Pattern) 装饰者模式--动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. ...

  8. Go 设计模式 - 装饰器模式

    装饰模式使用对象组合的方式动态改变或增加对象行为.Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式.使用匿名组合,在装饰器中不必显式定义转调原对象方法. 设计模式 装饰器模式 装饰器模式主要 ...

  9. 10. 设计模式-装饰者模式

    文章目录 设计模式-装饰者模式 1. 案例引出装饰者模式 2. 装饰者模式 2.1 装饰者模式定义 2.2 装饰者模式原理 2.3 装饰者模式解决星巴克咖啡订单问题 2.4 代码实现 抽象类Drink ...

最新文章

  1. java script valueof_Javascript new Date().valueOf()的作用与时间戳由来详解
  2. Keil uvision 5 MDK 安装教程
  3. 最佳买卖股票时机含冷冻期
  4. Left join后用and和where的区别
  5. Spring Boot学习笔记(1)
  6. Educational Codeforces Round 107 (Rated for Div. 2) 题解
  7. CloudIDE:为开发者写代码开启“加速”模式
  8. 管理Shader——Shader概览
  9. 常见病毒、木马进程速查表
  10. qt creator php扩展,用qt creator搭建开发、调试php扩展的环境
  11. java 反射覆盖方法,java – 确定一个方法是否覆盖使用反射的另一个?
  12. linux怎么安装网卡驱动固件,Linux网卡驱动的安装方式
  13. 5G及移动边缘计算(MEC)学习笔记(2)
  14. 四轴飞行器——转动惯量
  15. 最新借条模板,如何写
  16. sql连表查询、子查询、组合查询
  17. 从放弃本专业到直播编程,这女孩都经历了些什么?
  18. 习题3.3投骰子的随机游戏
  19. ggplot2-数据关系型图表
  20. 台式计算机开始不显示,台式机连接投影仪不显示怎么办

热门文章

  1. PostgreSQL数据库dblink和postgres_fdw扩展使用比较
  2. 获取当前的系统时间 年-月-日 小时-分钟-秒
  3. nginx配置一、二级域名、多域名对应(api接口、前端网站、后台管理网站)
  4. 《Python 3程序开发指南(第2版•修订版)》——1.2 Python的关键要素
  5. python 其他函数调用 __init__ 初始化的值
  6. mongodb 备份和恢复
  7. 使用 Button 类在 XNA 中创建图形按钮(九)
  8. c++面试题之内存分配
  9. 如何寻找outlook邮件附件直接修改保存后的文档
  10. 没有JS的前端:体积更小、速度更快!