装饰器模式

1、别称装饰模式,英文名Decorator

2、别称包装器模式,英文名Wrapper

 

出现背景

每个设计模式,都是大佬的血泪史,他们在做需求的时候,遇到这些问题,比如有1000个的函数,都需要增加一个计算函数执行时间的功能,你想想如果每个函数都去增加功能,多累啊,但是改出错怎么办,为了尽可能少的不修改原来的代码,出现了这个设计模式,常见的有Collections下synchronizedList方法,可以把

ArrayList与LinkedList转成线程安全的,靠的就是装饰器模式

 

1、同代理模式一样,都是通过不改变原有代码都基础上,为原有的方法增加那新的功能

 

2、代理模式是自己创建委托类对象,当然也是可以依赖传进来(通过构造方法)的委托类对象

 

3、而装饰器模式则依赖传进来的委托类对象

 

定义一个接口,表示具备的能力(功能)

 

public interface IExpression {
	public void shout();
}

谁实现了此接口,说明具备叫喊的能力

 

创建Cat类,实现了IExpression接口

public class Cat implements IExpression{

	@Override
	public void shout() {
		System.out.println("猫叫了一声");
	}

}

猫具备喊叫能力,但是觉得猫只叫了一声,能不能这只猫叫之前再稍微厉害点,可我们不想再改代码了……怕改出错

 

 创建第一个装饰器类

public class CatWrapper implements IExpression{
	
	public IExpression iex;
	
	public CatWrapper(IExpression iex) {
		this.iex = iex; //持有传进来的委托类对象iex
	}

	@Override
	public void shout() {
		System.out.println("稍微厉害点的猫");
		System.out.println("抖一抖胡子"); //为持有的委托类对象新增类能力
		iex.shout();
	}
	
}

1、它同样实现的是同一个接口

2、它需要持有实际需要增加功能的对象

3、在实际需要增加功能的方法中,加入需要的代码

 

再写一个装饰器类

public class MoreCatWrapper extends CatWrapper{

	
	public MoreCatWrapper(IExpression iex) {
		super(iex);
	}
	
	@Override
	public void shout(){
		System.out.println("大猫,比普通的更厉害");
		System.out.println("跺一跺地板");
		super.shout();
	}
	
}

1、为了进一步的扩充功能,我们直接继承了原来的装饰器类,而不是在原始类上增加

 

入口类Main使用装饰器类

public class Main {
	public static void main(String args[]) {
		IExpression baseIex = new Cat();
		baseIex.shout();
		
		IExpression bigIex = new MoreCatWrapper(baseIex);
		bigIex.shout();
	}
}

 输出结果:

猫叫了一声
大猫,比普通的更厉害
跺一跺地板
稍微厉害点的猫
抖一抖胡子
猫叫了一声

 

Anroid下的Wrapper模式,Activity就用了模式哦,请看源码

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient {
}
public class ContextThemeWrapper extends ContextWrapper {
}
public class ContextWrapper extends Context {
}
public abstract class Context {
}