装饰器模式常常用来动态的为已存在的类增加功能或者改变功能,而不用对原有类进行任何修改以造成对现有代码的影响。
比如,我们现在有一个订票功能OrderTicket。但是我们打算给他增加一些功能,比如订票之后发短信通知,或者发邮件通知。
听起来,似乎使用继承就能实现这个目标了。比如我们增加两个子类分别是SendMsgAfterOrderTicket(订票之后发短信),和SendEmailAfterOrderTicket(订票之后发邮件)。
这样我们调用相应的子类,覆盖父类的订票方法,在订票之后发送短信或者邮件。
但是如果我们需要既发送短信又发送邮件呢?如果在增加一个自动推送手机APP消息呢?如果希望只是选择性的选择其中的一种或者两种或者全部的通知呢?
继承的方式势必会造成混乱。如果通知方式更多,则更不用说了。
这就是装饰器模式显示作用的地方了:
请看代码:
package dp.decorator;
public interface OrderTicket{
public void placeOrder();
}
package dp.decorator;
public class OrderTicketImpl implements OrderTicket {
@Override
public void placeOrder() {
System.out.println("订了一张票");
}
}
package dp.decorator;
public class SendEmailAfterOrderTicket implements OrderTicket {
protected OrderTicket orderTicket;
public SendEmailAfterOrderTicket(OrderTicket orderTicket) {
this.orderTicket = orderTicket;
}
@Override
public void placeOrder() {
orderTicket.placeOrder();
System.out.println("发送电子邮件");
}
}
package dp.decorator;
public class SendMsgAfterOrderTicket implements OrderTicket {
protected OrderTicket orderTicket;
public SendMsgAfterOrderTicket(OrderTicket orderTicket) {
this.orderTicket = orderTicket;
}
@Override
public void placeOrder() {
orderTicket.placeOrder();
System.out.println("发送消息");
}
}
package dp.decorator;
public class SendNotificationAfterOrderTicket implements OrderTicket {
protected OrderTicket orderTicket;
public SendNotificationAfterOrderTicket(OrderTicket orderTicket) {
this.orderTicket = orderTicket;
}
@Override
public void placeOrder() {
orderTicket.placeOrder();
System.out.println("推送通知");
}
}
package dp.decorator;
public class Main {
public static void main(String args[]) {
OrderTicket orderTicket = new OrderTicketImpl();
System.out.println("------");
orderTicket.placeOrder();
OrderTicket sendEmailAfterOrderTicket = new SendEmailAfterOrderTicket(
orderTicket);
System.out.println("------");
sendEmailAfterOrderTicket.placeOrder();
OrderTicket sendMsgAfterOrderTicket = new SendMsgAfterOrderTicket(
orderTicket);
System.out.println("------");
sendMsgAfterOrderTicket.placeOrder();
OrderTicket sendNotificationAfterOrderTicket = new SendNotificationAfterOrderTicket(
orderTicket);
System.out.println("------");
sendNotificationAfterOrderTicket.placeOrder();
OrderTicket sendEmailThenNotificationAfterOrderTicket = new SendNotificationAfterOrderTicket(
new SendEmailAfterOrderTicket(orderTicket));
System.out.println("------");
sendEmailThenNotificationAfterOrderTicket.placeOrder();
OrderTicket sendEmailThenNotificationThenMsgAfterOrderTicket = new SendMsgAfterOrderTicket(
new SendNotificationAfterOrderTicket(
new SendEmailAfterOrderTicket(orderTicket)));
System.out.println("------");
sendEmailThenNotificationThenMsgAfterOrderTicket.placeOrder();
}
}
运行结果:
------
订了一张票
------
订了一张票
发送电子邮件
------
订了一张票
发送消息
------
订了一张票
推送通知
------
订了一张票
发送电子邮件
推送通知
------
订了一张票
发送电子邮件
推送通知
发送消息
从代码和结果我们可以看出,我们可以在不对原来的类进行任何改变的前提下,增加新的功能,然后还可以根据需要选择所增加的新功能,以及选择新功能的执行顺序,让代码之间的耦合降到最低。