装饰模式
前言
-
动态的为一个对象增加新的功能。
-
装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
一、实现细节
- Component抽象构件角色:
真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。 - ConcreteComponent 具体构件角色(真实对象):
io流中的FileInputStream、FileOutputStream - Decorator装饰角色:
持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。 - ConcreteDecorator具体装饰角色:
负责给构件对象增加新的责任。
二、具体实现
以咖啡为例,可以在咖啡中加糖、加奶…但是无论加什么,它仍然是一杯咖啡,只是对咖啡进行了味觉上的装饰。
1.实现抽象构件
/**
* 抽象构件
*/
public interface Component {
void showCoffee();
double showPrice();
}
2.实现具体构件
/**
* 具体构件
*/
public class Coffee implements Component{
private String name ;
private Double price;
public Coffee(String name, Double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public void showCoffee() {
System.out.println("的"+this.getName()+"咖啡");
}
@Override
public double showPrice() {
return this.getPrice();
}
}
3.实现装饰角色
/**
* 装饰抽象角色
*/
public abstract class Decorator implements Component{
private Component component;
public void setComponent(Component component) {
this.component = component;
}
@Override
public void showCoffee() {
component.showCoffee();
}
@Override
public double showPrice() {
return component.showPrice();
}
}
4.具体装饰角色
/**
* 具体装饰角色(加奶)
*/
public class Milk extends Decorator{
@Override
public void showCoffee() {
System.out.print("加奶");
super.showCoffee();
}
@Override
public double showPrice() {
return 15.0 + super.showPrice();
}
}
/**
* 具体装饰角色(加糖)
*/
public class Sugar extends Decorator{
@Override
public void showCoffee() {
System.out.print("加糖");
super.showCoffee();
}
@Override
public double showPrice() {
return 10.0 + super.showPrice();
}
}
5.测试类
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Coffee coffee = new Coffee("拿铁",55.0);
Decorator sugar = new Sugar();
Decorator milk = new Milk();
sugar.setComponent(coffee);
milk.setComponent(sugar);
milk.showCoffee();
System.out.println(milk.showPrice());
}
}
结果:
三、应用场景
- IO中输入流和输出流的设计
- Swing包中图形界面构件功能
- Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper类,增强了request对象的功能。
- Struts2中,request,response,session对象的处理
总结
装饰模式(Decorator)也叫包装器模式(Wrapper)
- 装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
- 优点
– 扩展对象功能,比继承灵活,不会导致类个数急剧增加
– 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
– 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。 - 缺点
– 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
– 装饰模式易于出错,调试排查比较麻烦。