Java装饰模式是一种结构性设计模式,允许在不修改对象的情况下向其添加行为。它对继承具有替代作用,可以在运行时动态地修改对象的行为。
实现方式
装饰模式有四种基本角色:
- 抽象组件(Component):定义对象的接口,可以是抽象类或接口,它负责定义组件的基本方法。
- 具体组件(ConcreteComponent):实现抽象组件定义的方法。
- 抽象装饰器(Decorator):维持一个指向组件对象的引用,并定义与组件接口一致的接口。
- 具体装饰器(ConcreteDecorator):向组件添加新功能。
以下是Java装饰模式的实现方式:
// 抽象组件
public abstract class Component {
public abstract void operate();
}
// 具体组件
public class ConcreteComponent extends Component {
public void operate() {
// ...
}
}
// 抽象装饰器
public abstract class Decorator extends Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
public void operate() {
component.operate();
}
}
// 具体装饰器
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operate() {
super.operate();
addNewFunction();
}
private void addNewFunction() {
// ...
}
}
运用场景
Java装饰模式常应用于以下场景:
- 当不能使用继承进行扩展时,可以使用装饰模式。
- 当需要在不同的时刻、不同的情况下,为一个对象增加额外的功能时,可以使用装饰模式。
以下是在Java中常见的运用场景:
Java IO流
Java IO流的输入/输出类库中,使用了装饰模式。 InputStream 和 OutputStream 为抽象组件, ByteArrayInputStream 和 ByteArrayOutputStream 为具体组件, FilterInputStream 和 FilterOutputStream 为抽象装饰器, BufferedInputStream 和 BufferedOutputStream 为具体装饰器。
如:
// 创建具体组件
InputStream fis = new FileInputStream("file.txt");
// 创建抽象装饰器
InputStream bis = new BufferedInputStream(fis);
Java Servlet API
Java Servlet API 中的 HttpServletRequestWrapper 和 HttpServletResponseWrapper 类使用了装饰模式。
如:
public class MyFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// 创建抽象装饰器并传递原始对象
MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) request);
MyHttpServletResponseWrapper responseWrapper = new MyHttpServletResponseWrapper((HttpServletResponse) response);
// 调用原始对象的方法
chain.doFilter(requestWrapper, responseWrapper);
// 在原始响应之后添加新的内容
responseWrapper.getWriter().append("<p>This is added by MyFilter.</p>");
}
}
总结
Java装饰模式允许在运行时动态地修改对象的行为,它与继承具有替代作用。Java IO流和Java Servlet API 中都广泛使用了装饰模式。在日常的Java开发中,也可以充分应用装饰模式来避免冗余代码,提高代码的复用性。