装饰模式是结构型模式的一种,属于十分常见的装饰模式。考虑具体场景:
如今不管是手机,还是智能汽车或者其他私人物品,现在均支持一个DIY的潮流,根据个人喜好以及经济能力,选配自己的组件。但核心都是该被DIY的物品。但是对于商家来说,任意的选配,就会有不一样的价格。如何清晰明了的解决这个需求,装饰模式则应运而生。
核心组件:
- 抽象组件接口,也可以是抽象类。即上述例子的手机或者汽车
- 具体的被装饰物。对于抽象组件的实现,具体的被装饰物
- 装饰物,对于抽象组件的时间,主要体现DIY的功能,因此,装饰物需要持有被装饰物的实体对象。
- 具体装饰物:不同的DIY对应的不同的实现。
UML图如下:
举得例子是:
核心组件是自行车,但是我们可以选择“装饰”自动驾驶的组件、或者飞行功能的组件。
代码演示如下:
/**
* 抽象组件
*/
public interface Bike {
String getDescription();
int getPrice();
}
/**
* 具体装饰对象
*/
public class BigBike implements Bike{
private String description = "大号自行车";
@Override
public String getDescription() {
return description;
}
@Override
public int getPrice() {
return 100;
}
}
/**
* 装饰对象
*/
public class BikeDecorate implements Bike{
private String description = "只是装饰的父类";
@Override
public String getDescription() {
return null;
}
@Override
public int getPrice() {
return 0;
}
}
/**
* "装饰自动骑行"
*/
public class AutoBike extends BikeDecorate{
private String description = "增加自动骑行";
private Bike bike;
public AutoBike(Bike bike) {
this.bike = bike;
}
@Override
public String getDescription() {
return bike.getDescription() + description;
}
@Override
public int getPrice() {
return bike.getPrice() + 50;
}
}
/**
* 装饰"飞行模式"
*/
public class FlyBike extends BikeDecorate{
private String description = "选配飞行模式";
private Bike bike;
public FlyBike(Bike bike) {
this.bike = bike;
}
@Override
public String getDescription() {
return bike.getDescription() + description;
}
@Override
public int getPrice() {
return bike.getPrice() + 90;
}
}
- 测试
public static void main(String[] args) {
// 被装饰对象
Bike bike = new BigBike();
// 选配自动骑行
FlyBike flyBike = new FlyBike(bike);
System.out.println(flyBike.getDescription());
System.out.println("价格:"+flyBike.getPrice());
System.out.println("------");
// 选配飞行模式
AutoBike autoBike = new AutoBike(bike);
System.out.println(autoBike.getDescription());
System.out.println("价格:"+autoBike.getPrice());
System.out.println("------");
// 选配自动骑行之后加配飞行模式
Bike superBike = new FlyBike(autoBike);
System.out.println(superBike.getDescription());
System.out.println("价格:"+superBike.getPrice());
}
有结果可以看出,使用装饰i模式,可以完全解决上述场景复杂多变的情形。随意而变的装饰。
-
优点: 装饰模式和继承都是要扩展功能,但是装饰模式可以提供更多的灵活性; 而且通过上面的测试我们可以看到,可以在原本的基础上灵活变动而不需要增加代码。例如在有了飞行车和自动车以后,并不需要再去定义一个飞行自动车。
-
缺点:当装饰物过多时,相应的类会越来越多,而且会出现很多嵌套,代码可能变的不易于理解。