来源:公众号轻文社
我觉得学设计模式,首先明白是什么?最终目标是学会怎么用到实际项目中。
github: https://github.com/zhang-shoukang/design-pattern
装饰设计模式
1.是什么?
装饰设计模式:顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。
2.案例:
爱美之心,人皆有之,
每个女生都想show出自己完美的以面,纵然也有素颜美女,但是渐渐单单的一个粉底,口红,足以让美女show出更完美的自己。
装饰设计模式,可以理解为美女通过粉底,口红装饰自己。
首先每个人要展示自己那必然有一个标准行为show(),我们将它抽象出来作为接口Showable。
interface Showable {
public void show();
}
当然,女友会这门功夫了,所以实现了此行为并施展其“美丽的脸庞”了,但此时只是原生态的素颜。
class Girl implements Showable {
public void show() {
System.out.print("女孩的素颜");
}
}
直接调用的话会是素面朝天直面惨淡的人生,这样当然达不到美颜效果了,何以登上人生巅峰。那么接下来要进行化妆了,这里必须依靠一种神秘而又昂贵的东西,化妆品登场了,它同样实现了Showable接口。
class Decorator implements Showable {
private Showable showable;
public Decorator(Showable showable){
super();
this.showable = showable;
}
public void show() {
System.out.print("粉饰(");
showable.show();
System.out.println(")!");
}
}
我们可以发现,在构造化妆品类的时候可以把女孩给注入进来,目的在于调用女孩的show方法,但对于其原本的具体行为装饰器一无所知,并且没有加入任何逻辑限制,它所做的无非是“画龙点睛”,“锦上添花”。接下来我们来运行一下看结果。
public class DecoratorTest {
public static void main(String[] args) {
Showable girl = new Girl();
Showable obj = new Decorator(girl);
obj.show();
}
}
运行结果: 粉饰(女孩的素颜)!
升级:
不过这样还没完, 仅仅是粉饰 太单调了吧,在这个浓妆艳抹的时代, 怎么着也得涂个大花脸哈哈啊哈!
原来的Decorator类太单调了, 我们把Decorator 抽象出来,之后让不同的装饰继承这个抽象类,实现不同的装饰。
定义抽象装饰类:
abstract class AbstractDecorator implements Showable {
protected Showable showable;
public AbstractDecorator(Showable showable) {
this.showable = showable;
}
public void show() {
showable.show();//直接调用不做加任何粉饰。
}
}
下面是打粉底的具体装饰类:
class FoundationMakeup extends AbstractDecorator{
public FoundationMakeup(Showable showable) {
super(showable);//调用化妆品父类注入
}
@Override
public void show() {
System.out.print("打粉底(");
showable.show();
System.out.print(")");
}
}
下面是涂口红的具体装饰类:
class Lipstick extends AbstractDecorator{
public Lipstick(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.print("涂口红(");
showable.show();
System.out.print(")");
}
}
测试类:
public class DecoratorTest2 {
public static void main(String[] args) {
//口红包裹粉底,再包裹女友。
Showable madeupGirl = new Lipstick(new FoundationMakeup(new Girl()));
madeupGirl.show();
//运行结果:涂口红(打粉底(女孩的脸庞))
}
}
输出结果: 涂口红(打粉底(女孩的素颜))
有没有发现测试类中的new Lipstick(new FoundationMakeup(new Girl())); 这种嵌套调用方式 有点眼熟,
没错,其实装饰器模式在JDK里就有很多应用,比如Java IO包里的众多流处理类。
比如:
new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
3.总结
要求装饰对象和被装饰对象实现相同的接口(这里就是指showable接口,show出自己)。此外,装饰对象需要持有被装饰对象的引用,因为被装饰对象原本是怎么装饰的,装饰对象并不知道。装饰对象只需要持有被装饰对象的引用,并且直接调用被装饰对象的原有的show方法即可完成装饰的扩展。层层包裹,层层装饰,每套一层就会多出一些功能出来,每个化妆品部件各司其职,不做和自己不相关的事,然后把部件层层叠加,并根据需求组装成型,以达最终的装饰目的。