您的位置:首页 > 其它

面向对象设计模式之---装饰模式(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恤,另外一种是喇叭裤。实现的代码如下:

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对象为空时结束。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息