Java 设计模式 之 装饰器模式(Decorator)
目录
装饰器模式(Decorator)
1、动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator 模式相比生成子类更加灵活。
2、要求装饰对象(如下所示的 Decorator)和被装饰对象(如下所示的 Source)实现同一个接口(如下所示的 Sourceable),装饰对象持有被装饰对象的实例,通过构造器传入。
3、装饰器模式的应用场景:
1)需要扩展一个类的功能。
2)动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)
缺点:产生过多相似的对象,不易排错!多层装饰比较复杂
3、下面使用代码实现上图:
package main.decoratorModel;
/**
* Created by Administrator on 2019/4/9 0009.
* 源接口
*/
public interface Sourceable {
//加法
public void addition(float a, float b);
//乘法
public void multiplication(float a, float b);
}
package main.decoratorModel;
import java.util.logging.Logger;
/**
* Created by Administrator on 2019/4/9 0009.
* 计算器
*/
public class Calculator implements Sourceable {
@Override
public void addition(float a, float b) {
Logger logger = Logger.getAnonymousLogger();
logger.info(a + " + " + b + " = " + (a + b));
}
@Override
public void multiplication(float a, float b) {
Logger logger = Logger.getAnonymousLogger();
logger.info(a + " * " + b + " = " + (a * b));
}
}
package main.decoratorModel;
import java.util.logging.Logger;
/**
* Created by Administrator on 2019/4/9 0009.
* 装饰器为在不改动 Source 的基础上,为 Source 对象动态的增加新的功能
*/
public class Decorator implements Sourceable {
private Calculator calculator;//将被装饰的对象通过参数传入
public Decorator(Calculator calculator) {
this.calculator = calculator;
}
@Override
public void addition(float a, float b) {
Logger logger = Logger.getAnonymousLogger();
logger.info("操作加法前的新功能...");
calculator.addition(a, b);
logger.info("操作加法后的新功能...");
}
@Override
public void multiplication(float a, float b) {
Logger logger = Logger.getAnonymousLogger();
logger.info("用户准备进行乘法运算:" + a + " * " + b);
calculator.multiplication(a, b);
logger.info("用户准备进行乘法运算完毕");
}
}
4、测试如下:
package main.test;
import main.decoratorModel.Calculator;
import main.decoratorModel.Decorator;
import main.decoratorModel.Sourceable;
import java.util.logging.Logger;
/**
* Created by Administrator on 2019/4/8 0008.
*/
public class Test {
public static void main(String[] args) {
Sourceable sourceable_calculator = new Calculator();
sourceable_calculator.addition(10F, 30F);
sourceable_calculator.multiplication(20F, 50F);
Logger logger = Logger.getAnonymousLogger();
logger.info("********************************************************");
Sourceable sourceable_decorator = new Decorator(new Calculator());
sourceable_decorator.addition(30F, 60F);
sourceable_decorator.multiplication(25F, 30F);
}
}
装饰器模式 VS 静态代理模式
1、装饰器模式与静态代理模式如果不仔细区分,则很容易混淆。区别的主要思想是:代理模式是控制控制访问,而装饰器模式是新增行为
2、相同点:
1)被装饰类与装饰类要求实现同一接口;静态代理类与目标类也要求实现同一接口
2)装饰类与静态代理类都可以实现增强目标类的功能
3)装饰类与静态代理类中都具有目标类的引用,目的都是为了在其中调用目标类的方 法
3、不同点
1)装饰器设计模式就是为了增强目标类;静态代理设计模式是为了保护和隐藏目标对象, 让客户类只能访问代理对象,而不能直接访问目标对象。
2)装饰类中的目标类的引用是通过带参构造器传入的;静态代理类中的目标类的引用, 一般都是在代理类中直接创建的,目的就是为了隐藏目标对象。
3)装饰类通常会先使用一个抽象类作为基类,基类一般不对目标对象进行增强,而是由不同的具体装饰类继承抽象装饰类后进行增强,这些具体的装饰者可以形成增强链,对目标对象进行连续增强。静态代理类会直接对目标对象进行增强,需要哪些增强的功能,一次性在静态代理类中完成,没有增强链的概念。
可以参考:http://www.runoob.com/design-pattern/decorator-pattern.html