Xavier's Blog

Decorator模式初探

| Comments

Decorator模式,又称装饰模式。在实际编程中,如果希望能在原有基础上动态的添加新的功能或者扩展已有功能,那么Decorator模式提供了一种很好的解决方案。Decorator模式如下图所示:

image

具体的实现类ConcreteComponent和装饰类Decorator均实现了Component接口,装饰类含有一个Component类作为其成员。这样,当需要在ConcreteComponent基础上添加新的功能时,只需扩展Decorator形成具有某一特定功能的Decorator即可。由于不同的Decorator都是遵循Component接口,当需要扩展新功能时,在原有的Decorator上再套一层Decorator就可以啦。

来用一个简单的例子解释一下吧。比如现在有个手机类SimplePhone,实现了Phone接口:

public interface Phone {
    String getDescription();
    int getCost();
}

package org.quxiao.phone;

public class SimplePhone implements Phone {

    @Override
    public String getDescription() {
        return "simple phone";
    }

    @Override
    public int getCost() {
        return 100;
    }

}

为了能动态增加功能,做一个抽象的Decorator:

public abstract class AbstractPhoneDecorator implements Phone {
    protected Phone phone;

    public AbstractPhoneDecorator(Phone phone)
    {
        this.phone = phone;
    }
}

现在需要给手机添加GPS模块,扩展抽象的Decorator:

public class GPSPhoneDecorator extends AbstractPhoneDecorator {

    public GPSPhoneDecorator(Phone phone) {
        super(phone);
    }

    @Override
    public String getDescription() {
        // TODO Auto-generated method stub
        return phone.getDescription() + " and GPS";
    }

    @Override
    public int getCost() {
        // TODO Auto-generated method stub
        return phone.getCost() + 100;
    }

}

同理,再添加蓝牙的模块:

public class BlueToothPhoneDecorator extends AbstractPhoneDecorator {

    public BlueToothPhoneDecorator(Phone phone) {
        super(phone);
    }

    @Override
    public String getDescription() {
        return phone.getDescription() + " and blue tooth";
    }

    @Override
    public int getCost() {
        return phone.getCost() + 200;
    }

}

这样,我们就可以给SimplePhone类动态的添加模块了

public class Main {

    public static void main(String[] args) {
        Phone simplePhone = new SimplePhone();
        Phone GPSPhone = new GPSPhoneDecorator(simplePhone);
        Phone myPhone = new GPSPhoneDecorator(new BlueToothPhoneDecorator(new SimplePhone()));

        System.out.println("simplePhone description : " + simplePhone.getDescription());
        System.out.println("simplePhone cost : " + simplePhone.getCost());
        System.out.println("GPSPhone description : " + GPSPhone.getDescription());
        System.out.println("GPSPhone cost : " + GPSPhone.getCost());
        System.out.println("myPhone description : " + myPhone.getDescription());
        System.out.println("myPhone cost : " + myPhone.getCost());
    }
}

simplePhone description : simple phone simplePhone cost : 100 GPSPhone description : simple phone and GPS GPSPhone cost : 200 myPhone description : simple phone and blue tooth and GPS myPhone cost : 400

其实,Java I/O库中就是用了Decorator模式。

在基于Stream的输入中,所有数据都抽象成InputStream类,其子类FilterInputStream就相当于InputStream的装饰类。BufferedInputStream, CheckedInputStream, CipherInputStream, DataInputStream, DeflaterInputStream, DigestInputStream,InflaterInputStream, LineNumberInputStream, ProgressMonitorInputStream, PushbackInputStream都扩展自FilterInputStream,每个都对应于一个特定的功能。比如哦BufferedInputStream具有缓存功能,DataInputStream可将读出基本(primitive)类型的数据。因此,当我们使用Java I/O库进行输入输出时,总会生成一堆的类,就像这样:

DataInputStream dis = new DataInputStream( new BufferedInputStream( new FileInputStream(FILE_LOC)));

之前一直不明白为什么Java的输入输出会这么麻烦,原来是因为用到了Decorator模式。现在明白了其中的原理,也觉得不那么复杂了。

Comments