简单装扮

需求:要求写一个可以给人搭配不同的服饰的系统,比如类似QQ、网络游戏或论坛都有的Avatar系统。

/*** 需求:要求写一个可以给人搭配不同的服饰的系统,比如类似QQ、网络游戏或论坛都有的Avatar系统。*/
public class Person {private String name;public Person(String name) {this.name = name;}public void wearTShirts() {System.out.print("大T恤  ");}public void wearBigTrouser() {System.out.print("垮裤  ");}public void wearSneakers() {System.out.print("破球鞋  ");}public void wearSuit() {System.out.print("西装  ");}public void wearTie() {System.out.print("领带  ");}public void wearLeatherShoes() {System.out.print("皮鞋  ");}public void show() {System.out.print("装扮的" + name);}
}

客户端

public class Client {public static void main(String[] args) {Person person = new Person("张无忌");System.out.println("第一种装扮:");person.wearTShirts();person.wearBigTrouser();person.wearSneakers();person.show();System.out.println();System.out.println("第二种装扮:");person.wearSuit();person.wearTie();person.wearLeatherShoes();person.show();}
}


问题:如果需要增加“超人”的装扮,该如何做呢?虽然修改Person类就可以了,但是违背了开闭原则,所以应该将这些服饰都写成子类。

改进版本

public class Person {private String name;public Person(String name) {this.name = name;}public void show() {System.out.print("装扮的" + name);}
}
/*** 服饰*/
public abstract class Finery {public abstract void show();
}
public class BigTrouser extends Finery {@Overridepublic void show() {System.out.print("垮裤 ");}
}
public class LeatherShoes extends Finery {@Overridepublic void show() {System.out.print("皮鞋  ");}
}
public class Sneakers extends Finery {@Overridepublic void show() {System.out.print("破球鞋  ");}
}
public class Suit extends Finery {@Overridepublic void show() {System.out.print("西装  ");}
}
public class Tie extends Finery{@Overridepublic void show() {System.out.print("领带  ");}
}
public class TShirts extends Finery {@Overridepublic void show() {System.out.print("大T恤 ");}
}

客户端

public class Client {public static void main(String[] args) {Person person = new Person("张无忌");System.out.println("第一种装扮:");Finery tShirts = new TShirts();Finery bigTrouser = new BigTrouser();Finery sneakers = new Sneakers();tShirts.show();bigTrouser.show();sneakers.show();person.show();System.out.println();System.out.println("第二种装扮:");Finery suit = new Suit();Finery tie = new Tie();Finery leatherShoes = new LeatherShoes();suit.show();tie.show();leatherShoes.show();person.show();}
}

问题:虽然这里做到了服饰与人的分类,但只是一个一个列了出来,我们需要把所需的功能按正确的顺序串联起来进行控制。
这里不能使用建造者模式,因为建造者模式要求建造的过程必须是稳定的,而这个例子,建造过程是不稳定的。

装饰者模式

装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

Component

Component是定义一个对象接口,可以给这些对象动态地添加职责

public abstract class Component {public abstract void operation();
}

Decorator

Decorator 装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。

public class Decorator extends Component {protected Component component;// 设置Componentpublic void setComponent(Component component) {this.component = component;}// 重写operation(),实际执行的是Component的operation();@Overridepublic void operation() {if (component != null) {component.operation();}}
}

ConcreteComponent

ConcreteComponent定义了一个具体的对象,也可以给这个对象添加一些职责。
如果只有一个ConcreteComponent而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

public class ConcreteComponent extends Component{@Overridepublic void operation() {System.out.println("具体对象的操作");}}

ConcreteDecorator

ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

public class ConcreteDecoratorA extends Decorator{// 本类的独有功能,以区别于ConcreteDecoratorBprivate String addedState;@Overridepublic void operation() {// 首先运行原Component的operation()super.operation();// 再执行本类的功能,如addedState,相当于对原Component进行了装饰addedState = "New State";System.out.println("具体装饰对象A的操作");}
}
public class ConcreteDecoratorB extends Decorator {@Overridepublic void operation() {// 首先运行原Component的operation()super.operation();// 再执行本类的功能,如addedBehavior(),相当于对原Component进行了装饰addedBehavior();System.out.println("具体装饰对象B的操作");}// 本类的独有方法,以区别于ConcreteDecoratorAprivate void addedBehavior() {}
}

客户端

装饰模式是利用setComponent()来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。

public class Client {public static void main(String[] args) {// 装饰的方法是:首先用ConcreteComponent实例化对象cConcreteComponent c = new ConcreteComponent();ConcreteDecoratorA d1 = new ConcreteDecoratorA();ConcreteDecoratorB d2 = new ConcreteDecoratorB();// 然后用ConcreteDecoratorA的实例化对象d1来包装cd1.setComponent(c);d2.setComponent(d1);// 再用ConcreteDecoratorB的对象d2包装d1,最终执行d2的operation();d2.operation();}
}

简单总结:装饰者Decorator继承了Component,调用具体的装饰者的operation方法时,会先调用Component的operation方法,然后再调用装饰者自身添加的功能。

装饰者模式案例改进

Person(被装饰者)

这里Person就是具体的ConcreteComponent,没有Component,Decorator继承Person这个ConcreteComponent就可以。

public class Person {private String name;public Person() {}public Person(String name) {this.name = name;}public void show() {System.out.print("装扮的" + name);}
}

Finery(服饰类,装饰者)

装饰者继承具体的被装饰者,增强show()

/*** 服饰类(Decorator)*/
public class Finery extends Person {protected Person component;// 打扮public void decorate(Person component) {this.component = component;}public void show() {if(component!=null) {component.show();}}
}

具体服饰类

/*** 具体服饰类*/
public class TShirts extends Finery {@Overridepublic void show() {System.out.print("大T恤 ");super.show();}
}
public class BigTrouser extends Finery {@Overridepublic void show() {System.out.print("垮裤 ");super.show();}
}
public class LeatherShoes extends Finery {@Overridepublic void show() {System.out.print("皮鞋  ");super.show();}
}
public class Sneakers extends Finery {@Overridepublic void show() {System.out.print("破球鞋  ");super.show();}
}
public class Suit extends Finery {@Overridepublic void show() {System.out.print("西装  ");super.show();}
}
public class Tie extends Finery {@Overridepublic void show() {System.out.print("领带  ");super.show();}
}

客户端

public class Client {public static void main(String[] args) {Person person = new Person("张无忌");System.out.println("第一种装扮:");Finery sneakers = new Sneakers();Finery bigTrouser = new BigTrouser();Finery tShirts = new TShirts();sneakers.decorate(person);bigTrouser.decorate(sneakers);tShirts.decorate(bigTrouser);tShirts.show();System.out.println();System.out.println("第二种装扮:");Finery leatherShoes = new LeatherShoes();Finery tie = new Tie();Finery suit = new Suit();leatherShoes.decorate(person);tie.decorate(leatherShoes);suit.decorate(tie);suit.show();}
}

装饰者模式总结

装饰模式是为已有功能动态地添加更多功能的一种方式。

当系统需要新功能的时候,需要向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。但问题在于在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度。而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。

而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。

装饰模式的优点:把类中的装饰功能从类中搬移去除,这样可以简化原有的类。可以有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。

注:本文内容源自程杰的《大话设计模式》

大话设计模式——装饰者模式相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. Spring设计模式(装饰器模式)

    Spring设计模式(装饰器模式) 模式的定义: 装饰者模式定义: ​ 动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案. 模式的结构图 : 模式包含角 ...

最新文章

  1. 手把手教您如何用U盘给电脑安装WIN10系统详细教程
  2. 谈谈密码学的数学原理
  3. Qt Creator添加新的自定义向导
  4. pycharm mysql安装_PyCharm安装连接MySQL
  5. android 字体荧光效果,Android-荧光效果
  6. 【Java】JSR 内存屏障
  7. Linux-管道(day09)
  8. 求解一个flapping问题,双端口可学一个MAC
  9. QUALCOMM MDM9X15 LCD初始化流程
  10. 使用EasyExcel实现excel的简单读写操作
  11. JavaScript制作页面倒计时器
  12. python csv 大文件_python 快速把超大txt文件转存为csv的实例
  13. 虚拟机ubuntu14.04编译MPI版本NAMD
  14. [数据结构]递归树:借助树求解递归算法的时间复杂度
  15. 笨方法学python 习题29-31
  16. 关于数据库中FK的简单理解以及应用
  17. 图片马 php 菜刀,图片马的制作以及菜刀的使用
  18. 2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
  19. 这些95后表示:是时候打破对程序员的刻板印象了!
  20. Maya云渲染怎么操作?看这一篇就够了

热门文章

  1. php预处理_php预处理是什么
  2. 可变悬挂与空气悬挂的区别_可变悬架与空气悬架的区别
  3. PowerCLI 通过vCenter批量更改所有的esxi主机名称和DNS
  4. Fibonacci数列求余 C语言
  5. antlr4读书笔记
  6. 半实物仿真测试平台集成开发环境技术背景及总体介绍
  7. java 切面顺序_spring 多个切面如何有序执行
  8. 【java基础:FileWriter】方式一:创建文本文件并写入字符内容
  9. 无法更新计算机的启动设置安装,“windows 无法更新计算机的启动配置。安装无法继续”这样解决...
  10. C++头文件 <algorithm>的 常用函数(详细)