装饰着模式:简单来说,就是现在有一个主体功能,需要在这个主体功能之外加一些附属功能,而且主体功能和附属功能都可以独立运行,类似于基础款和升级款的概念。就像是在主体功能之外加了一层装饰,所以叫装饰者模式,也叫包装者模式。
其实如果光从这个需求看,我们最直接的应该是想到继承。但是继承使用起来并不方便,如果我的附属功能有很多,而且主体功能也有很多具体的实现,那么使用继承将是一个非常大的工作量而且不利于扩展。
举个例子来说明一下:
比如我要买车,买车可以有很多选择,首先可能会有我们钟爱的品牌,品牌下有可能有各种型号,选中了某款车型之后,销售人员肯定就坐下来给你推销各种附加功能,什么真皮座椅,防滑垫,酷酷的轮毂,再加个尾翼等等。那么后面的这些附属功能就可以理解为装饰者模式中的装饰,其实完全不要这些,这辆车照样可以跑,不过经济不紧张的话再加些装饰也是可以让人心情愉悦的哈。
被装饰者,也就是主体功能,在我们这个例子中就是车
// 被包装
public interface Car {
public String desc();
public Double price();
}
根据品牌我们实现两个具体的被装饰者
// byd
public class Byd implements Car{
@Override
public String desc() {
return "BYD ";
}
@Override
public Double price() {
return 1000.00;
}
}
// Tesla
public class Tesla implements Car{
@Override
public String desc() {
return "Tesla";
}
@Override
public Double price() {
return 800.00;
}
}
然后就是装饰者了,这里我们要让装饰者实现主体功能,同时需要把被装饰者集成到自己的属性中。在被装饰之后,至少可以有主体功能,也可以在此基础之上进行扩展。
public abstract class CarWrapper implements Car{
private Car car;
public CarWrapper(Car car) {
this.car = car;
}
@Override
public String desc() {
return car.desc();
}
@Override
public Double price() {
return car.price();
}
}
具体的装饰着类
// 真皮座椅
public class CarWrapperDermis extends CarWrapper{
public CarWrapperDermis(Car car) {
super(car);
}
@Override
public String desc() {
return super.desc()+"+真皮座椅";
}
@Override
public Double price() {
return super.price()+666;
}
}
// 双倍安全气囊
public class CarWrapperDoubleSafe extends CarWrapper{
public CarWrapperDoubleSafe(Car car) {
super(car);
}
@Override
public String desc() {
return super.desc() +" +双倍安全气囊";
}
@Override
public Double price() {
return super.price()+888;
}
}
测试使用
public class Client {
public static void main(String[] args) {
// 被装饰者,主体功能
// Car car = new Byd();
Car car = new Tesla();
// 装饰者,需要接收一个被装饰者作为参数
CarWrapper carWrapper = new CarWrapperDermis(car);
System.out.println(carWrapper.desc()+" : "+carWrapper.price());
System.out.println("========================");
// 这个设计的巧妙之处在于这里,包装器类的对象本身还可以作为被包装的对象传给新的包装器
carWrapper = new CarWrapperDoubleSafe(carWrapper);
System.out.println(carWrapper.desc()+" : "+carWrapper.price());
}
}
小结一下:这个装饰着模式的关键点就在于:装饰者既继承自被装饰者,同时又拥有被装饰者作为一个属性。这样的设计就是为了使装饰者在提供被装饰者的主体功能之外,还能对它进行扩展。而且这样做之后,有一个巧妙的地方就是,装饰者本身又可以作为另外一个装饰者的参数,也就是可以进行多次包装。这样的话对于大量繁复的附属功能来说就可以随意的进行扩展使用。可扩展性特别好。