面向对象设计模式之---装饰模式(Decorator Pattern)
2018-03-26 11:03
465 查看
装饰模式给我的感觉就有点像一个人穿衣服,或者从更专业一点的角度来说,有点像Java中文件读取时管道要套上一层又一层的“衣服”一样。这是一个链式的过程。
装饰模式的定义是:
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式的UML类图如下:
Componet是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcentrateDecorator就是具体的装饰对象,起到给Component添加职责的功能。——《大话设计模式》
有没有看了这段话还是有点晕?还是回到本文开头提到的穿衣服 的应用场景,我是这么理解的:比如人穿衣服,宠物也可以穿衣服,人和宠物都可以算是生物。所以,生物就是这个Component接口,人或者是宠物就是ConcentrateComponent类;衣服就是Decorator类,而具体穿了什么衣服就是ConcreteDecorator类。
我们现在想把小明穿衣服这个场景模拟成代码,有时如果ConcreteComponent类只有一个,并且没有抽象的话,就不需要Component接口了 比如我们实现的只有人穿衣服,就可以直接把Component和ConcreteComponent类进行合并,只要有一个Person类就行了。如果Decorator类有类似的情况也可以如此操作。
人穿衣服 这个事件的UML类图如下:
这里我们就拿了两周衣服,一种是T恤,另外一种是喇叭裤。实现的代码如下:
上述代码运行的结果为:
最后我想补充的是这段代码的执行过程,为什么会有这样的执行结果
首先,先看main方法的头三行。
它们分别实例化了人、T恤、喇叭裤对象
接着,人先穿上了喇叭裤,再穿上了T恤。
然后,重点在那个show方法。
a.从代码的层面来看,是从喇叭裤对象来调用show方法的,所以,先输出了穿喇叭裤。
我们不妨看看最先调用show方法的这个喇叭裤类对象的结构:
可以发现,喇叭裤套了T恤对象,T恤对象又包了人。可以说是非常形象了,人就是被衣服包着嘛~
b.在喇叭裤类的show方法中,调用了super.show()。因为喇叭裤类的基类是服饰类,所以转而调用服饰类的show(),注意:此时有一个向上对象转型,将喇叭裤向上转型为服饰,又因为这两个类在属性上是没有差异的,所以,当在基类的show方法中调用this.component.show()时,就相当于往前进一步,进入了T恤对象,直到this.component对象为空时结束。
装饰模式的定义是:
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式的UML类图如下:
Componet是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcentrateDecorator就是具体的装饰对象,起到给Component添加职责的功能。——《大话设计模式》
有没有看了这段话还是有点晕?还是回到本文开头提到的穿衣服 的应用场景,我是这么理解的:比如人穿衣服,宠物也可以穿衣服,人和宠物都可以算是生物。所以,生物就是这个Component接口,人或者是宠物就是ConcentrateComponent类;衣服就是Decorator类,而具体穿了什么衣服就是ConcreteDecorator类。
我们现在想把小明穿衣服这个场景模拟成代码,有时如果ConcreteComponent类只有一个,并且没有抽象的话,就不需要Component接口了 比如我们实现的只有人穿衣服,就可以直接把Component和ConcreteComponent类进行合并,只要有一个Person类就行了。如果Decorator类有类似的情况也可以如此操作。
人穿衣服 这个事件的UML类图如下:
这里我们就拿了两周衣服,一种是T恤,另外一种是喇叭裤。实现的代码如下:
import java.util.*; //人类 class Person { private String name; public Person(String name) { this.name = name; } public Person(){} public void show() { System.out.println(this.name+"的装扮"); } } //服饰类 class Finery extends Person { protected Person component; public Finery() { super(); } public void decorate(Person component) { this.component = component; } public void show() { if(this.component != null) { this.component.show(); } } } //具体的服饰 class TShirts extends Finery { public void show() { System.out.print("穿大T恤"); super.show(); } } class BigTrouser extends Finery { public void show() { System.out.print("穿喇叭裤"); super.show(); } } public class Main { public static void main(String[] args) { Person p = new Person("小明"); TShirts ts = new TShirts(); BigTrouser bt = new BigTrouser(); ts.decorate(p); bt.decorate(ts); bt.show(); } }
上述代码运行的结果为:
穿喇叭裤穿大T恤小明的装扮
最后我想补充的是这段代码的执行过程,为什么会有这样的执行结果
首先,先看main方法的头三行。
Person p = new Person("小明"); TShirts ts = new TShirts(); BigTrouser bt = new BigTrouser();
它们分别实例化了人、T恤、喇叭裤对象
接着,人先穿上了喇叭裤,再穿上了T恤。
然后,重点在那个show方法。
a.从代码的层面来看,是从喇叭裤对象来调用show方法的,所以,先输出了穿喇叭裤。
我们不妨看看最先调用show方法的这个喇叭裤类对象的结构:
可以发现,喇叭裤套了T恤对象,T恤对象又包了人。可以说是非常形象了,人就是被衣服包着嘛~
b.在喇叭裤类的show方法中,调用了super.show()。因为喇叭裤类的基类是服饰类,所以转而调用服饰类的show(),注意:此时有一个向上对象转型,将喇叭裤向上转型为服饰,又因为这两个类在属性上是没有差异的,所以,当在基类的show方法中调用this.component.show()时,就相当于往前进一步,进入了T恤对象,直到this.component对象为空时结束。
相关文章推荐
- 基于东北F4的设计模式情景剧——第一幕 装饰模式(Decorator Pattern)
- .NET设计模式(10):装饰模式(Decorator Pattern)
- 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- C#设计模式之装饰模式(Decorator Pattern)
- 24种设计模式--装饰模式【Decorator Pattern】
- 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰设计模式 Learn Decorator Design Pattern in Easy Steps
- 浅谈 java 设计模式--装饰模式(Decorator pattern)
- DOTA版设计模式——装饰模式[Decorator Pattern]
- .NET设计模式(10):装饰模式(Decorator Pattern)(转)
- JAVA设计模式之 装饰模式【Decorator Pattern】
- 装饰模式例子(Decorator Pattern)
- Java之装饰模式(Decorator Pattern)
- (第Ⅲ部分 结构型模式篇) 第9章 装饰模式(Decorator Pattern)
- .NET设计模式-装饰模式(Decorator Pattern)
- android设计模式-装饰模式(Decorator Pattern)
- 装饰模式(Decorator pattern)应用----日志信息输出
- 装饰模式(Decorator Pattern)