博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
装饰器(Decorator)模式
阅读量:5808 次
发布时间:2019-06-18

本文共 2988 字,大约阅读时间需要 9 分钟。

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

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

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

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

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

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

结构图:

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

1 package ooad.design.Decorator;2 3 public interface IWeapon {4   public String getName();5   public int getAttack();6 }

 

1 package ooad.design.Decorator;2 3 public interface IRole {4      public void attack(IWeapon weapon);5 6 }

接着我们创建武器:

1 package ooad.design.Decorator; 2  3 public class Gun implements IWeapon { 4     private String name; 5      6  7     public Gun(String name) { 8         super(); 9         this.name = name;10     }11 12     @Override13     public String getName() {14         15         return this.name;16     }17 18     @Override19     public int getAttack() {20         21         return 200;22     }23 24     25 26 }

 

 然后我们创建角色:

1 package ooad.design.Decorator; 2  3 public class Gunmen implements IRole { 4     private String name; 5      6  7     public Gunmen(String name) { 8         super(); 9         this.name = name;10     }11     public String getName() {12         return name;13     }14 15 16     public void setName(String name) {17         this.name = name;18     }19 20 21     @Override22     public void attack(IWeapon weapon) {23        System.out.println(this.name+"使用"+weapon.getName()+"进行攻击,造成的伤害值为:"+weapon.getAttack());    24     }25 26 }

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

1 package ooad.design.Decorator;2 3 public abstract class Decorator implements IWeapon{4     public abstract int getAttack();5 6 }

 

宝石类:

1 package ooad.design.Decorator; 2  3 public class Ruby extends Decorator { 4     private IWeapon weapon; 5         6     public Ruby(IWeapon weapon) { 7         super(); 8         this.weapon = weapon; 9     }10 11     @Override12     public String getName() {13         14         return "增加了红宝石的"+weapon.getName();15     }16 17     @Override18     public int getAttack() {19         20         return 5+weapon.getAttack();21     }22 23 }

 

 来个测试:

1 package ooad.design.Decorator; 2  3 public class Test { 4  5     public static void main(String[] args) { 6         IRole r =new Gunmen("枪手"); 7         IWeapon w=new Gun("火箭枪"); 8         r.attack(w); 9         w=new Ruby(w);10         r.attack(w);11     }12 13 }

 

 最终结果:

枪手使用火箭枪进行攻击,造成的伤害值为:200

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

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

r.attack(w);

r.attack(w);

结果呢则是:

枪手使用火箭枪进行攻击,造成的伤害值为:200

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

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

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

 

 

转载地址:http://ziybx.baihongyu.com/

你可能感兴趣的文章
Android状态栏实现沉浸式模式
查看>>
让你的APP实现即时聊天功能
查看>>
iOS 绝对路径和相对路径
查看>>
使用Openfiler搭建ISCSI网络存储
查看>>
应用新安全组 - 每天5分钟玩转 OpenStack(116)
查看>>
Guid.NewGuid().ToString()的几种格式
查看>>
生产制造追溯系统
查看>>
4.3. 键盘设置
查看>>
iOS - UIViewController
查看>>
MYSQL子查询与连接
查看>>
Appium+python自动化20-查看iOS上app元素属性
查看>>
准备 overlay 网络实验环境 - 每天5分钟玩转 Docker 容器技术(49)
查看>>
论文笔记之:Large Scale Distributed Semi-Supervised Learning Using Streaming Approximation
查看>>
IntPtr 转 string
查看>>
一文搞懂各种 Docker 网络 - 每天5分钟玩转 Docker 容器技术(72)
查看>>
学生名单
查看>>
(转) 多模态机器翻译
查看>>
【官方文档】Nginx负载均衡学习笔记(三) TCP和UDP负载平衡官方参考文档
查看>>
opencv安装指南
查看>>
矩阵常用归一化
查看>>