装饰器(Decorator)模式
2015-07-18 09:40
309 查看
1 装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。通常给对象添加功能,要么直接修改对象添加相应的功能,要么派生对应的子类来扩展,抑或是使用对象组合的方式。显然,直接修改对应的类这种方式并不可取。在面向对象的设计中,而我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式,可以很灵活的给对象添加所需要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。总之,装饰模式是通过把复杂的功能简单化,分散化,然后再运行期间,根据需要来动态组合的这样一个模式。
2 问题提出:在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?
这时我们就可以使用装饰器模式
同样的我们还是来举个例子看看:
设计一个小游戏 游戏中很多的角色(角色包括: 枪手Gunmen,刀客swordsman等), 角色拥有武器,武器包括(刀knife(150),枪gun(200),棍(100)),
游戏中我们可以通过给武器加上一些宝石(蓝宝石,红宝石,绿宝石) 来加强武器的攻击力。
红宝石每增加一颗 攻击力 +5;ruby
蓝宝石每增加一颗 攻击力+10;sapphire
绿宝石每增加一颗 攻击力 +20
结构图:
首先还是先创建两个接口;
接着我们创建武器:
然后我们创建角色:
因为武器需要宝石来装饰,所以呢我们创建一个装饰的抽象类
宝石类:
来个测试:
最终结果:
枪手使用火箭枪进行攻击,造成的伤害值为:200
枪手使用增加了红宝石的火箭枪进行攻击,造成的伤害值为:205
如果想要用两颗红宝石我们就可以这样:
r.attack(w);
r.attack(w);
结果呢则是:
枪手使用火箭枪进行攻击,造成的伤害值为:200
枪手使用增加了红宝石的增加了红宝石的火箭枪进行攻击,造成的伤害值为:210
增加了红宝石的增加了红宝石的 这样看起来不舒服吧,该怎样去判断他到底增加了几颗宝石,我们就显示几颗宝石呢?
例子中的角色,武器,装饰的宝石,我就没有全部写出来了!
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
增加了红宝石的增加了红宝石的 这样看起来不舒服吧,该怎样去判断他到底增加了几颗宝石,我们就显示几颗宝石呢?
例子中的角色,武器,装饰的宝石,我就没有全部写出来了!
相关文章推荐
- 第二版银行储蓄系统
- 排序算法之三路划分的快速排序
- (转)使用VS实现XML2CS
- android 在特殊应用的特殊功能,以帮助通信系统的问题
- ExtJs动态生成treepanel的Json格式
- input清除默认样式及兼容问题的解决方法
- 关于Page翻页效果, PageViewConrtoller
- A星算法(VC版源码)
- 关联对话框方法
- 黑马程序员——第六天(包)
- PLSQL连接远程ORACLE数据库中文乱码解决
- android studio安装
- Event Handling Guide for iOS--事件驱动指南
- 精度: 3%+3个字 什么意思
- 使用hydra暴力破解web登录界面
- 使用Canvas和Paint自己绘制折线图
- iOS 带参数函数体和不带参数函数体的实现与xcode单步调试
- mac 卸载mysql shell脚本
- 详解Django中的form库的使用
- 远程控制