面向对象设计模式之---装饰模式(Decorator Pattern)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mgsky1/article/details/79695236

装饰模式给我的感觉就有点像一个人穿衣服,或者从更专业一点的角度来说,有点像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对象为空时结束。

猜你喜欢

转载自blog.csdn.net/mgsky1/article/details/79695236