最近在学习设计模式,看了很多篇帖子,现对此模式的理解做一些笔记,方便后续查阅。
参考博文:https://www.cnblogs.com/java-my-life/archive/2012/04/20/2455726.html
http://blog.csdn.net/pnjlc/article/details/52701929
一、装饰者模式
装饰模式:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
二、个人理解。
装饰者模式是在不改变原有方法的情况下对原有方法的的一种扩展。即在程序运行原有方法之前或者之后做一些事情。
三、代码示例。
1.原有基类(方法,借口)
package com.gs.design.model.decorator;
/**
* 普通接口,打印一句话
* @author user
*
*/
public interface Component {
public void printOneSentence();
}
2.原有方法的具体实现。
package com.gs.design.model.decorator;
/**
* 打印一句话接口的具体实现
* @author user
*
*/
public class ComponentImpl implements Component {
@Override
public void printOneSentence() {
System.out.println("here is Component implement...");
}
}
3. 定义基类的装饰器,需传入原有基类的对象。
package com.gs.design.model.decorator;
/**
* 装饰类,我需要在打印一句话的这个方法之前或者之后做一些事情(具体实现在装饰类的子类)。
* @author user
*
*/
public class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void printOneSentence() {
component.printOneSentence();
}
}
4. 装饰类子类A,具体要做的事情。
package com.gs.design.model.decorator;
/**
* 装饰类的具体'实现',比如我要在输出一句话这个方法之前 再说一句helloword!
* @author user
*
*/
public class DecoratorSonA extends Decorator {
public DecoratorSonA(Component component) {
super(component);
}
@Override
public void printOneSentence() {
//before
System.out.println("这是装饰子类A.我在说话之前说----Hello world!");
super.printOneSentence();
}
}
5. 装饰类子类B,我需要在做的其他事情,
package com.gs.design.model.decorator;
/**
* 装饰类的具体'实现',比如我要在输出一句话这个方法之后再说一句-Good bye world!!
* @author user
*
*/
public class DecoratorSonB extends Decorator {
public DecoratorSonB(Component component) {
super(component);
}
@Override
public void printOneSentence() {
super.printOneSentence();
//after
System.out.println("这是装饰子类B.我在说话之后说----Good bye world!");
}
}
6. 测试类(客户端)
package com.gs.design.model.decorator;
import org.junit.Test;
/**
* 测试装饰类功能。
* @author user
*
*/
public class DecoratorTest {
@Test
public void testA(){
//原来接口,输出一句话的接口
Component component = new ComponentImpl();
//装饰,对输出一句话这个方法进行装饰。,
Component decoratorA = new DecoratorSonA(component);
//调用装饰后的方法(component原方法不变,仅是在执行这个方法之前在做一些事情。),
decoratorA.printOneSentence();
//结果
//这是装饰子类A.我在说话之前说----Hello world!
//here is Component implement...
}
@Test
public void testB(){
//原来接口,输出一句话的接口
Component component = new ComponentImpl();
//装饰,对输出一句话这个方法进行装饰。,
Component decoratorB = new DecoratorSonB(component);
//调用装饰后的方法(component原方法不变,仅是在执行这个方法之后在做一些事情。),
decoratorB.printOneSentence();
//结果
//here is Component implment...
//这是装饰子类B.我在说话之后说----Good bye world!
}
@Test
public void testAB(){
//原来接口,输出一句话的接口
Component component = new ComponentImpl();
//装饰,对输出一句话这个方法进行装饰。,
Component decoratorB = new DecoratorSonB(component);
Component decoratorA = new DecoratorSonA(decoratorB);
//调用装饰后的方法(component原方法不变,仅是在执行这个方法之后在做一些事情。),
decoratorA.printOneSentence();
//结果
//这是装饰子类A.我在说话之前说----Hello world!
//here is Component implment...
//这是装饰子类B.我在说话之后说----Good bye world!
}
}
四、疑问
虽然学习了装饰者模式,但是现在还是觉得有些疑惑。(写出疑惑一来是希望大牛解惑,二是提醒自己后续多注意这里的问题)
1. 这种模式最终是对对象的"装饰",那这样的话 我还是需要在调用处,再去实例化装饰器,传入原对象。
这样的话,假如一个项目中有100处都使用了原方法printOneSentence().我需要在执行这个方法之前输出“hello world!”
为此写了一个装饰器。
那么岂不是在这100处调用的地方都需要实例化一个装饰器,传入原对象Component decoratorA = new DecoratorSonA(component);,然后在用 装饰器对象decoratorA 调用printOneSentence()。这样做和直接写一个公共方法,在原方法之前调用有什么区别?
2. 这种模式的好处到底在哪里?
3. 最近也看了python的装饰模式。感觉就比java的这种好很多,写一个嵌套函数,在原方法上加上注解调用此函数就可以。方便很多