装饰者模式
装饰者模式
1.基础知识
定义∶
在不改变原有对象的基础之上,将功能附加到对象上
提供了比继承更有弹性的替代方案(扩展原有对象功能)
类型∶结构型
通过构造方法,传入子类,包装子类,在装饰者类中用父类接收基类子类对象,返回父类对象,可以做到无限包装
适用场景
扩展一个类的功能或给一个类添加附加职责
动态的给一个对象添加功能,这些功能可以再动态的撤销
优点
继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能
通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
符合开闭原则
缺点
会出现更多的代码,更多的类,增加程序复杂性
动态装饰时,多层装饰时会更复杂
相关设计模式
装饰者模式和代理模式
装饰者模式和适配器模式
2.实战
这里用奶茶举个栗子,单杯奶茶卖8块钱,椰果1份2块,布丁1份3块,我想要加2份椰果,1份布丁。
UML如图:
/**
* 奶茶装饰者类,类中组合奶茶抽象类
*/
public abstract class AbstractDecorator extends ATeaMilk {
//继承一个抽象类,并装配这个抽象对象
private ATeaMilk aTeaMilk;
public AbstractDecorator(ATeaMilk aTeaMilk) {
this.aTeaMilk = aTeaMilk;
}
protected abstract void doSomething();
@Override
protected String getDesc() {
return this.aTeaMilk.getDesc();
}
@Override
protected int cost() {
return this.aTeaMilk.cost();
}
}
/**
* 奶茶基类
* @Author LYS
* @Date 2022/1/18 16:38
* @Version 1.0
*/
public abstract class ATeaMilk {
protected abstract String getDesc();
protected abstract int cost();
}
/**
* 椰果装饰类,1份2块钱
*
* @Author LYS
* @Date 2022/1/18 16:41
* @Version 1.0
*/
public class CoconutDecorator extends AbstractDecorator {
public CoconutDecorator(ATeaMilk aTeaMilk) {
super(aTeaMilk);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc() + " 加一份椰果2块";
}
//一份椰果2块钱
@Override
protected int cost() {
return super.cost() + 2;
}
}
/**
* 布丁类 一份布丁3块钱
* @Author LYS
* @Date 2022/1/18 16:44
* @Version 1.0
*/
public class PuddingDecorator extends AbstractDecorator{
public PuddingDecorator(ATeaMilk aTeaMilk) {
super(aTeaMilk);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc() + " 加一份布丁3块";
}
//一份布丁3块钱
@Override
protected int cost() {
return super.cost() + 3;
}
}
/**
* @Author LYS
* @Date 2022/1/18 16:40
* @Version 1.0
*/
public class TeaMike extends ATeaMilk {
@Override
protected String getDesc() {
return "奶茶8块";
}
//奶茶默认8块一杯
@Override
protected int cost() {
return 8;
}
}
public class Test {
public static void main(String[] args) {
//ATeaMilk是所有类的抽象类
ATeaMilk aTeaMilk;
//TeaMike是ATeaMilk的实现类 定义一杯普通奶茶 定义方法cost是8
aTeaMilk = new TeaMike();
//CoconutDecorator();传入ATeaMilk基类 的实现类 定义方法cost是super.cost()+2;也就是8+2 返回ATeaMilk对象
aTeaMilk = new CoconutDecorator(aTeaMilk);
aTeaMilk = new CoconutDecorator(aTeaMilk);
//PuddingDecorator();传入ATeaMilk基类 的实现类 定义方法cost是super.cost()+3;也就是8+3 返回ATeaMilk对象
aTeaMilk = new PuddingDecorator(aTeaMilk);
//这里调用cost()方法,应为当前aTeaMilk已经包装了好几层。这个调用就是不断的入栈出栈调用的
System.out.println(aTeaMilk.getDesc() + " 销售价格:" + aTeaMilk.cost());
}
}
3.源码
java io
增加缓存类有很多
BufferedReader类继承Reader 组合reader 就是一个装饰者类,可以无限的装饰继承reader的子类类似实战中的奶茶类
public class BufferedReader extends Reader {
private Reader in;
public BufferedReader(Reader in, int sz) {
super(in);
if (sz <= 0)
throw new IllegalArgumentException("Buffer size <= 0");
this.in = in;
cb = new char[sz];
nextChar = nChars = 0;
}
FilterInputStream 继承InputStream ,类里又组装了InputStream in
class FilterInputStream extends InputStream {
/**
* The input stream to be filtered.
*/
protected volatile InputStream in;
spring中TransactionAwareCacheDecorator处理缓存和同步事务 这个类就是Cache的装饰者类
public class TransactionAwareCacheDecorator implements Cache {
private final Cache targetCache;
public TransactionAwareCacheDecorator(Cache targetCache) {
Assert.notNull(targetCache, "Target Cache must not be null");
this.targetCache = targetCache;
}
wrapper结尾要么是装饰者模式要么是适配器模式,看具体的类的继承实现结构
mybatis中