题外话
设计模式之前已经看过一遍书了,但是只是有个模糊的印象,经过一段时间的开发思考,打算写写设计模式的应用。
介绍
装饰模式顾名思义就是对原有的东西增加一些包装,再原有的基础上增添东西。如果我们想扩展已有的功能,首先会想到继承,通过重写父类方法,super来调用父类的实现,再添加自己的额外逻辑。而装饰器模式是一种替代继承的方案,可以扩展扩展已有的功能。装饰器模式实际就是给一个对象添加一些新的功能,是动态的增加,相比于继承增加子类更加灵活。
例子
假如原类是一个汽车类,汽车类作为原类有运输功能。但是现在要给不同的汽车上装额外的功能,一个汽车上可以听音乐功能,一个汽车上可以上网功能;
如果想要增加新功能,不可以直接修改原类的代码,那么增添一个包装类,对原有的汽车类进行扩展。
- 抽象构造角色
// 抽象构造角色
public interface ICar {
public void transport();
}
- 具体构造角色
// 具体构造角色
public class CarImpl implements ICar{
@Override
public void transport() {
System.out.println("运输货物!");
}
}
- 抽象装饰角色
//抽象装饰角色
public abstract class DecoratorCar implements ICar {
private ICar iCar;
public DecoratorCar(ICar iCar) {
this.iCar = iCar;
}
public void transport() {
iCar.transport();
}
}
- 具体装饰角色
// 具体装饰角色
public class ConcreteCarA extends DecoratorCar{
public ConcreteCarA(ICar iCar) {
super(iCar);
}
public void transport() {
super.transport();
System.out.println("听音乐");
}
}
main测试:
public static void main(String[] args) {
ICar iCar = new CarImpl();
ICar concreteCarA = new ConcreteCarA(iCar);
concreteCarA.transport();
}
实际应用中的设计
使用缓冲流读取文件的例子,分析第一句中装饰器模式的设计应用。
public static void main(String[] args) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/BugReport.txt"));
int length = 0;
byte[] arr = new byte[2048];
while ((length = bis.read(arr)) != -1) {
System.out.println(new String(arr, 0, length));
}
bis.close();
}
① 抽象构造角色:
public abstract class InputStream implements Closeable {
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
}
② 具体构造角色:
public class FileInputStream extends InputStream {
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
}
③ 抽象装饰角色:
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
}
④ 具体装饰角色:
public class BufferedInputStream extends FilterInputStream {
public BufferedInputStream(InputStream in) {
this(in, defaultBufferSize);
}
public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
}
说明:
此功能就是在FileInputStream文件流装饰上缓存的功能。目标也是增强文件流的功能。关键点在于抽象装饰角色是否持有抽象构造角色的引用,引用抽象构造角色就间接引用了具体构造角色,这样就可以通过构造器传入来实现装饰进而达到功能的增强。
总结
- 装饰类实际就是一个为原有类增添新功能的模式(也可以为原功能删除,但是得是原类方法级层次上的,方法体内是不可以的)。
- 装饰类其实也把核心的功能和装饰的功能分开了。
网友评论