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

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

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

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

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

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

结构图:

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

 package ooad.design.Decorator;

 public interface IWeapon {
public String getName();
public int getAttack();
}
 package ooad.design.Decorator;

 public interface IRole {
public void attack(IWeapon weapon); }

接着我们创建武器:

 package ooad.design.Decorator;

 public class Gun implements IWeapon {
private String name; public Gun(String name) {
super();
this.name = name;
} @Override
public String getName() { return this.name;
} @Override
public int getAttack() { return 200;
} }

然后我们创建角色:

 package ooad.design.Decorator;

 public class Gunmen implements IRole {
private String name; public Gunmen(String name) {
super();
this.name = name;
}
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public void attack(IWeapon weapon) {
System.out.println(this.name+"使用"+weapon.getName()+"进行攻击,造成的伤害值为:"+weapon.getAttack());
} }

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

 package ooad.design.Decorator;

 public abstract class Decorator implements IWeapon{
public abstract int getAttack(); }

宝石类:

 package ooad.design.Decorator;

 public class Ruby extends Decorator {
private IWeapon weapon; public Ruby(IWeapon weapon) {
super();
this.weapon = weapon;
} @Override
public String getName() { return "增加了红宝石的"+weapon.getName();
} @Override
public int getAttack() { return 5+weapon.getAttack();
} }

来个测试:

 package ooad.design.Decorator;

 public class Test {

     public static void main(String[] args) {
IRole r =new Gunmen("枪手");
IWeapon w=new Gun("火箭枪");
r.attack(w);
w=new Ruby(w);
r.attack(w);
} }

最终结果:

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

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

r.attack(w);

r.attack(w);

结果呢则是:

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

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

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

装饰器(Decorator)模式的更多相关文章

  1. 装饰器(Decorator)模式

    public interface IDoThings { public void doSomeThing(); } public class DoThings implements IDoThings ...

  2. Head First 设计模式 —— 03. 装饰器 (Decorator) 模式

    思考题 有如下类设计: 如果牛奶的价钱上扬,怎么办?新增一种焦糖调料风味时,怎么办? 造成这种维护上的困难,违反了我们之前提过的哪种设计原则? P82 取出并封装变化的部分,让其他部分不收影响 多用组 ...

  3. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  4. python 装饰器(decorator)

    装饰器(decorator) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 装饰器(decorator)是一种高级Python语 ...

  5. python语法32[装饰器decorator](转)

    一 装饰器decorator decorator设计模式允许动态地对现有的对象或函数包装以至于修改现有的职责和行为,简单地讲用来动态地扩展现有的功能.其实也就是其他语言中的AOP的概念,将对象或函数的 ...

  6. Python的程序结构[8] -> 装饰器/Decorator -> 装饰器浅析

    装饰器 / Decorator 目录 关于闭包 装饰器的本质 语法糖 装饰器传入参数 1 关于闭包 / About Closure 装饰器其本质是一个闭包函数,为此首先理解闭包的含义. 闭包(Clos ...

  7. Python_高阶函数、装饰器(decorator)

    一.变量: Python支持多种数据类型,在计算机内部,可以把任何数据都看成一个“对象”,而变量就是在程序中用来指向这些数据对象的,对变量赋值就是把数据和变量给关联起来. 对变量赋值x = y是把变量 ...

  8. python 语法之 装饰器decorator

    装饰器 decorator 或者称为包装器,是对函数的一种包装. 它能使函数的功能得到扩充,而同时不用修改函数本身的代码. 它能够增加函数执行前.执行后的行为,而不需对调用函数的代码做任何改变. 下面 ...

  9. python函数编程-装饰器decorator

    函数是个对象,并且可以赋值给一个变量,通过变量也能调用该函数: >>> def now(): ... print('2017-12-28') ... >>> l = ...

  10. 【Angular专题】 (3)装饰器decorator,一块语法糖

    目录 一. Decorator装饰器 二. Typescript中的装饰器 2.1 类装饰器 2.2 方法装饰器 2.3 访问器装饰器 2.4 属性装饰器 2.5 参数装饰器 三. 用ES5代码模拟装 ...

随机推荐

  1. kettle学习

    数据etl工具,主要用做数据采集和清洗 待续...

  2. bootstrap table 前端搜索

    1.bootstrap-table对于前端的搜索可以通过官网设置,但发现前端搜索出现bug,网上找到一个bootstrap-table的扩充js  bootstrap-table-mytoolbar. ...

  3. HDU 4920 矩阵乘积 优化

    Matrix multiplication Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  4. [转载]金融行业 DevOps 解决方案概述

    2009 年 6 月份,John Allspaw 及 Paul Hammond 在速度大会 (Velocity) 上分享了在 Flickr 中如何通过加强 Dev(开发团队)和 Ops(运维团队)之间 ...

  5. 一些小案例_C#

    下面是一些小的案例.(C#) 1,求一段数第n位 //1 1 2 3 5 8 求30位 //规律是前两位之和是第三位数, ;//定义第一位 ;//定义第二位 ;//总和 ; i < ; i++) ...

  6. 【转载】uwp 获取系统字体库

    效果图: 要获取到字体库首先要在 NuGet 添加 SharpDx.Direct2D1  api: /// <summary> /// 获取系统字体库列表 /// </summary ...

  7. TDateTimePicker中Date与Time的误导

    Delphi DateTime,Date,Time TDateTimePicker DateTimeDateTimeDateTimePicker 一.DateTime,Date,Time存储方式本质上 ...

  8. pyqt5 Button.click 报错:argument 1 has unexpected type 'NoneType'

    如上所示,在括号中,添加‘lambda:’,就可以成功运行,不知道为啥. 参考:https://blog.csdn.net/flhsxyz/article/details/79220936?utm_s ...

  9. [ZJOI2010]基站选址(线段树优化dp)

    坑待填. \(Code\ Below:\) #include <bits/stdc++.h> #define lson (rt<<1) #define rson (rt< ...

  10. JavaScript基础(1)-ECMAScript

    一.JavaScript简介 1.JavaScript历史背景 布兰登 • 艾奇(Brendan Eich,1961年-),1995年在网景公司,发明的JavaScript. 刚开始JavaScrip ...