Android设计模式之中的一个个样例让你彻底明确装饰者模式(Decorator Pattern)
导读
这篇文章中我不会使用概念性文字来说明装饰者模式。由于通常概念性的问题都非常抽象。非常难懂。使得读者非常难明确究竟为什么要使用这样的设计模式。我们设计模式的诞生,肯定是前辈们在设计程序的时候遇到了某种困难,为了避免这样的苦难的发生,从而设计出来的这样的设计模式,所以这篇文章中我会带领大家遇见这样的困难,从而使用设计模式解决这样的困难,最后大家就会明确什么是设计者模式,什么时候应该使用设计者模式以及怎样使用设计者模式了
首先我们先来看一下装饰者模式的UML图是什么样子的。图中各个类的含义不懂没有关系,以下我会用一个形象的样例来一一介绍他们,相信大家看完后肯定就明确了
假设不用装饰者设计模式会出现什么问题?
这里我不准备用一些概念性的文字来说明什么是装饰者模式,我就要用一个实际的样例来形象的说明什么是装饰者模式。
比方我们玩网络游戏。我们都要先创建一个角色对吧,这些角色每一个人创建出来的都不一样,由于角色肯定能够依据用户的审美来个性化打造,但是每一个角色最開始的能力都是一样的,不会由于一个玩家给他捏了一张特别帅的脸而变得特别的厉害。
那么这个角色肯定是一个接口,这就是UML图中的Conponent接口
/**
* 游戏角色
*/
public interface Avatar {
String describe();
}
非常easy,仅仅有一个方法,我们仅仅用来演示。真正的游戏角色不可能仅仅有这么简单。describe方法用来描写叙述这个角色。
好,我们玩游戏肯定有职业对吧,假设我们这款游戏仅仅设计了4种职业:战士(Worrior),法师(Mage),猎人(Hunter),术士(Warlock)。我们要创建4个实现类。这就相应ConcreteComponent类
public class Worrior implements Avatar {
@Override
public String describe() {
return "战士";
}
}
public class Mage implements Avatar {
@Override
public String describe() {
return "法师";
}
}
public class Hunter implements Avatar {
@Override
public String describe() {
return "猎人";
}
}
public class WarLock implements Avatar {
@Override
public String describe() {
return "术士";
}
}
好了,如今我们已经创建好4种职业的游戏角色了。如今我们的玩家认为太单调了,全部相同职业的角色都长一个样子,你们应该同意我们在创建角色的时候能够改动角色的外观。比方选择头发颜色。
这可怎么办,我们有4种职业啊,每种职业提供3种颜色的头发。我们得再创建12个子类啊,并且之前设计的4个实现类的作用也就不大了,由于大家肯定都去改变一下头发的颜色。
好。先硬着头皮来写吧。
public class WorriorWithRedHair implements Avatar{
@Override
public String describe() {
return "战士+红颜色头发";
}
}
public class WorriorWithGreenHair implements Avatar{
@Override
public String describe() {
return "战士+绿颜色头发";
}
}
public class WorriorWithBlueHair implements Avatar{
@Override
public String describe() {
return "战士+蓝颜色头发";
}
}
public class MageWithRedHair implements Avatar{
@Override
public String describe() {
return "法师+红颜色头发";
}
}
public class MageWithGreenHair implements Avatar{
@Override
public String describe() {
return "法师+绿颜色头发";
}
}
public class MageWithBlueHair implements Avatar{
@Override
public String describe() {
return "法师+蓝颜色头发";
}
public class HunterWithRedHair implements Avatar{
@Override
public String describe() {
return "猎人+红颜色头发";
}
}
public class HunterWithGreenHair implements Avatar{
@Override
public String describe() {
return "猎人+绿颜色头发";
}
}
public class HunterWithBlueHair implements Avatar{
@Override
public String describe() {
return "猎人+蓝颜色头发";
}
public class WarLockWithRedHair implements Avatar{
@Override
public String describe() {
return "术士+红颜色头发";
}
}
public class WarLockWithGreenHair implements Avatar{
@Override
public String describe() {
return "术士+绿颜色头发";
}
}
public class WarLockWithBlueHair implements Avatar{
@Override
public String describe() {
return "术士+蓝颜色头发";
}
好了。加班到半夜,最终写完了。第二天上班,老板来找你了,如今我们的玩家越来越多了,他们反映说我们的角色还是太单调。我们还要让玩家能够选择上衣的颜色和裤子的颜色,上衣有5种颜色,裤子有5种颜色。
听完这个需求,我想你也应该吐血了。
比方玩家A会选择战士+红色头发+白色上衣+蓝色裤子,玩家B会选择术士+蓝色头发+白色上衣+黄色裤子。
这组合也太多了。这得写多少个实现类。
这样的方法肯定是行不通的。
使用装饰者模式怎样解决这个问题?
这时公司来了个大牛。他听说了这个情况,接下了这个需求,你心想他一定是疯了。但是第二天他就完毕了任务。你吃了一大惊,赶紧去看他的代码是怎么实现的。原来这位大牛使用了你连听都没说过的装饰者设计模式。
首先他设计了一个类。实现了Avatar接口,并且传入了一个Avatar对象,这就相应UML图中的Decorator
public class AvatarDecorator implements Avatar {
private Avatar av;
public AvatarDecorator(Avatar avatar){
av = avatar;
}
@Override
public String describe() {
return av.describe();
}
}
我们看到他里面持有一个Avatar类型的对象,在describe方法中实际调用的也是av的describe对象,我们传入的Avatar对象也就是我们须要进行装饰的对象了。
好。如今我们先来设计头发颜色的装饰类
public class RedHair extends AvatarDecorator {
public RedHair(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+红色头发";
}
}
public class GreenHair extends AvatarDecorator {
public GreenHair(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+绿色头发";
}
}
public class BlueHair extends AvatarDecorator {
public BlueHair(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+蓝色头发";
}
}
我们看到。我们的构造方法是调用的super()的构造方法,也就是调用的AvatarDecorator的构造方法,我们的describe中也先调用了super.describe()然后后面加上了我们的装饰内容,也就是说我们传进来的一个Avatar对象被我们装饰了。
这就相当于UML中的ConcreteDecorator。
好了,如今玩家想要创建一个角色的话就能够这样创建出来
//红色头发战士
Avatar avatar1 = new RedHair(new Worrior());
//绿色头发术士
Avatar avatar2 = new GreenHair(new WarLock());
接下来我们再设计上衣和裤子的装饰类
public class WhiteJacket extends AvatarDecorator {
public WhiteJacket(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+白色上衣";
}
}
public class RedJacket extends AvatarDecorator {
public RedJacket(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+红色上衣";
}
}public class BlackJacket extends AvatarDecorator {
public BlackJacket(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+黑色上衣";
}
}public class GreenJacket extends AvatarDecorator {
public GreenJacket(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+绿色上衣";
}
}public class BlueJacket extends AvatarDecorator {
public BlueJacket(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+蓝色上衣";
}
}
public class WhitePants extends AvatarDecorator {
public WhitePants(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+白色裤子";
}
}
public class BlackPants extends AvatarDecorator {
public BlackPants(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+黑色裤子";
}
}
public class RedPants extends AvatarDecorator {
public RedPants(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+红色裤子";
}
}
public class GreenPants extends AvatarDecorator {
public GreenPants(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+绿色裤子";
}
}
public class BluePants extends AvatarDecorator {
public BluePants(Avatar avatar) {
super(avatar);
}
@Override
public String describe() {
return super.describe()+"+蓝色裤子";
}
}
好了。如今我们就能够随意组合我们的角色了
//绿色头发猎人穿着白色上衣和黑色裤子
Avatar avatar3 = new GreenHair(new WhiteJacket(new BlackPants(new Hunter())));
//红色头发法师穿着红色上衣和白色裤子
Avatar avatar4 = new RedHair(new RedJacket(new WhitePants(new Mage())));
有图有真相
Android设计模式之中的一个个样例让你彻底明确装饰者模式(Decorator Pattern)的更多相关文章
- 浅谈设计模式--装饰者模式(Decorator Pattern)
挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...
- 设计模式学习--装饰者模式(Decorator Pattern)
概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...
- c#设计模式之装饰器模式(Decorator Pattern)
引子 在面向对象语言中,我们常常会听到这样一句话:组合优于继承.那么该如何去理解这句话呢? 下面我将以游戏装备为模型用简单的代码去展示它 先创建一个装备的抽象类,然后创建刀枪2个具体的业务子类 pub ...
- 23种设计模式之装饰器模式(Decorator Pattern)
装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包 ...
- python 设计模式之装饰器模式 Decorator Pattern
#写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...
- 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)
在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...
- C#设计模式——装饰者模式(Decorator Pattern)
一.例子在软件开发中,我们往往会想要给某一类对象增加不同的功能.比如要给汽车增加ESP.天窗或者定速巡航.如果利用继承来实现,就需要定义无数的类,Car,ESPCar,CCSCar,SunRoofCa ...
- C#设计模式之装饰者模式(Decorator Pattern)
1.概述 装饰者模式,英文名叫做Decorator Pattern.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 2 ...
- HeadFirst设计模式读书笔记(3)-装饰者模式(Decorator Pattern)
装饰者模式:动态地将责任附件到对象上.若要扩展功能,装饰者提东了比继承更有弹性的替代方案. 装饰者和被装饰对象有相同的超类型 你可以用一个或者多个装饰者包装一个对象. 既然装饰者和被装饰对象有相同的超 ...
随机推荐
- 【bzoj3435】[Wc2014]紫荆花之恋 替罪点分树套SBT
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- spring 解决中文乱码问题
spring 解决中文乱码问题 使用spring的前提下在web.xml中配置 <filter> <filter-name>encodingFilter</filter- ...
- BZOJ3260 跳 【组合数】
题目 邪教喜欢在各种各样空间内跳.现在,邪教来到了一个二维平面. 在这个平面内,如果邪教当前跳到了(x,y),那么他下一步可以选择跳到以下4个点: (x-1,y),(x+1,y),(x,y-1),(x ...
- Web系统从Oracle迁移至MySQL
前两天领导给了个活,数据库迁移,原来的系统是用的Oracle数据库,现在要改成MySql,当时没多想就接下来了,原来的系统用的框架式SSI,于是大概想了下需要作调整无非以下几点 第一 数据库迁移 第二 ...
- Eat the Trees(hdu 1693)
题意:在n*m的矩阵中,有些格子有树,没有树的格子不能到达,找一条或多条回路,吃完所有的树,求有多少中方法. 第一道真正意义上的插头DP,可参考陈丹琦的<基于连通性状态压缩的动态规划问题> ...
- struts2 package 属性说明
package节点是整个配置的核心部分.每个package,从语义上讲,其实代表了每一个独立的模块.在这个模块中,你可以定义隶属于这个模块的行为方式,而与其他的模块没有关系.所以,每个package都 ...
- 通过 jsp+ajax+servlet+webservice 远程访问天气预报服务
通过 jsp+ajax+servlet+webservice 远程访问天气预报服务 - webservice 客户端访问的方式 1. java代码来访问 2. ajax 方式异步加 ...
- Heritrix3.0.0启动介绍
下面开始使用Heritrix3.0.0 进 入CMD(开始->运行),进入Heritrix3.0.0所在目录,我这里是D:/heritrix/heritrix3.0.0/bin,这里 大家截图也 ...
- python commands 模块
commands 模块 通过python调用系统命令 只适用于linux commands是提供linux系统环境下支持使用shell命令的一个模块 commands.getoutput(cmd) 只 ...
- hdu 4525(数学)
威威猫系列故事——吃鸡腿 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tota ...