Decorator:装饰者模式
先代码
接口或抽象类:
package h.l.demo.decorator;
/**
* @author: Is-Me-Hl
* @date: 2020年2月14日
* @Description: 接口或抽象类
*/
public interface Computer {
// 被装饰的行为
public void work();
}
子类或实现类:
package h.l.demo.decorator;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月14日
* @Description: 基本功能
*/
public class BasicFuncComputer implements Computer {
@Override
public void work() {
System.out.println("Computer基本功能");
}
}
装饰类:
package h.l.demo.decorator;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月14日
* @Description: 装饰类
*/
public class ComputerDecorator implements Computer {
/**
* ComputerDecorator构造方法是关键,当然这里也可以手动写setComputer方法,
* 只不过相应的地方需要做适当修改
*/
private Computer computer;
public ComputerDecorator(Computer computer) {
this.computer = computer;
}
@Override
public void work() {
if (this.computer != null) {
this.computer.work();
}
}
// setComputer方式实现
/*private Computer computer;
public void setComputer(Computer computer) {
this.computer = computer;
}
@Override
public void work() {
if (this.computer != null) {
this.computer.work();
}
}*/
}
装饰类子类(两个):
package h.l.demo.decorator;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月14日
* @Description: 具体的装饰类A,重写装饰的内容
*/
public class ConcreteDecoratorA extends ComputerDecorator {
public ConcreteDecoratorA(Computer computer) {
super(computer);
}
@Override
public void work(){
super.work();
System.out.println("我给Computer装饰了A功能");
}
// 对应父类的setComputer方式实现
/*@Override
public void work(){
super.work();
System.out.println("我给Computer装饰了A功能");
}*/
}
package h.l.demo.decorator;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月14日
* @Description: 具体的装饰类B,重写装饰的内容
*/
public class ConcreteDecoratorB extends ComputerDecorator {
public ConcreteDecoratorB(Computer computer) {
super(computer);
}
@Override
public void work(){
super.work();
System.out.println("我给Computer装饰了B功能");
}
// 对应父类的setComputer方式实现
/*@Override
public void work(){
super.work();
System.out.println("我给Computer装饰了B功能");
}*/
}
测试类:
package h.l.demo.decorator;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月14日
* @Description: 测试
*/
public class TestMainEnter {
public static void main(String[] args) {
// 电脑基本功能
BasicFuncComputer bfComputer = new BasicFuncComputer();
bfComputer.work();
System.out.println("-----------");
// 基本功能基础上,动态装饰功能A
ComputerDecorator conA = new ConcreteDecoratorA(bfComputer);
conA.work();
System.out.println("-----------");
// 基本功能基础上,动态装饰功能B
ComputerDecorator conB = new ConcreteDecoratorB(bfComputer);
conB.work();
System.out.println("-----------");
// 基本功能既装饰A。也装饰B
ComputerDecorator conC = new ConcreteDecoratorB(new ConcreteDecoratorA(new BasicFuncComputer()));
conC.work();
// 对应setComputer实现
// 电脑基本功能
/*BasicFuncComputer bfComputer = new BasicFuncComputer();
bfComputer.work();
System.out.println("-----------");
// 基本功能基础上,动态装饰功能A
ComputerDecorator conA = new ConcreteDecoratorA();
conA.setComputer(bfComputer);
conA.work();
System.out.println("-----------");
// 基本功能基础上,动态装饰功能B
ComputerDecorator conB = new ConcreteDecoratorB();
conB.setComputer(bfComputer);
conB.work();
System.out.println("-----------");
// 基本功能既装饰A。也装饰B
ComputerDecorator conC = new ConcreteDecoratorB();
conC.setComputer(conA);
conC.work();*/
}
}
测试结果:
后分析
- 个人建议:写代码是件幸福的事,So,do it
装饰者模式,可以动态的添加、组合新的功能,提供了比继承更为灵活的对象功能扩展能力。使用场景,就是某些对象需要动态添加新功能或者组合功能的时候,可以使用到装饰者模式。从上面代码来讲,我们有一台电脑,用BasicFunComputer类来实现了电脑的基本功能,而后,实际上电脑可以提供的不仅仅是一些基本功能如office办公,他还支持了上网冲浪的功能(当然这个需要缴费,弄个宽带),以及看电视、听音乐等等一些功能,那么对于这些功能,并不是每一个人都需要的,所以他可以根据自己的喜好随意组合。上述代码写了一个装饰类,通过对被装饰子类实例的包装,以达到我们所想要的组合方式。(网上有人说,装饰者模式是继承的替代方案,仔细想想,也是可以这么理解,就拿上面的例子而言,电脑有基本功能office办公,那么有些人希望自己的电脑再加个上网冲浪的功能,有些人说我不要上网,网费太贵,我要个单机游戏玩玩就好,还有些人甚至说,我就想听歌音乐,冲浪、游戏我都没兴趣,那么对于如此繁多的组合情况,通过继承的方式一个个是写对应的子类,感觉不太现实。这个时候装饰者模式的功能组合就体现出价值了。当然这里还要提醒的是新功能组合的先后顺序在实际开发中要根据业务尤其小心组合,否则会有意想不到的尴尬~)。
其他参考:
InputStream is=System.in;
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
//等价于
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
其他例子:参考自《大话设计模式》
装饰者模式章节:人物换装。上衣有三件,裤子有四条,鞋子有五双,帽子有六顶,人物根据不同的选择,最后输出人物的装扮。功能组合问题,就可以用上装饰者模式了
注:以上文章仅是个人总结,若有不当之处,望不吝赐教