1. 结构型模式的定义
拿生活中的例子来说明,对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮、更温馨、更实用。
在软件设计中,对已有对象(新房)的功能进行扩展(装修),可以使对象的功能变得更加健全。
把通用功能封装在装饰器中,用到的地方进行调用。装饰模式是一种用于替代继承的技术,使用对象之间的关联关系取代类之间的继承关系。引入装饰类,扩充新功能。
2. 装饰者模式的角色
角色包含4个:
- 抽象构件
- 具体构件
- 抽象装饰类
- 具体装饰类
3. 具体案例说明
我们要实现显示列表框(ListBox),显示文本框(TextBox),显示窗体(Window )功能等组件,这些组件都基于抽象类Component来实现。
然后统一的装饰者是要给这些组件添加黑色边框(BlackBoarderDecorator )和滚动条(ScrollBarDecorator)功能。
4. UML图表示
5. 具体代码实现
1.组件类
package Decorator; // 装饰者模式
abstract class Component {
public abstract void display();
}
2.组件装饰者
package Decorator;
public class ComponentDecorator extends Component{
private Component component; // 维持对抽象构件类型对象的引用
public ComponentDecorator(Component component){
this.component = component;
}
public void display() {
component.display();
}
}
3.继承类ListBox
package Decorator;
public class ListBox extends Component{
public void display() {
System.out.println("显示列表框!");
}
}
4.继承类TextBox
package Decorator;
public class TextBox extends Component{
public void display() {
System.out.println("显示文本框!");
}
}
5.继承类Window
package Decorator;
public class Window extends Component{
public void display() {
System.out.println("显示窗体!");
}
}
6.黑框装饰者
package Decorator;
public class BlackBoarderDecorator extends ComponentDecorator{
public BlackBoarderDecorator(Component component) {
super(component);
}
public void display() {
this.setBlackBoarder();
super.display();
}
public void setBlackBoarder() {
System.out.println("为构件增加黑色边框!");
}
}
7.滚动条装饰者
package Decorator;
public class ScrollBarDecorator extends ComponentDecorator{
public ScrollBarDecorator (Component component) {
super(component); // 调用父类构造函数
}
public void display() {
this.setScrollBar();
super.display();
}
public void setScrollBar() {
System.out.println("为构件增加滚动条!");
}
}
8.客户端调用
package Decorator; // 装饰者模式
public class Client {
public static void main(String args[]) {
Component component,componentSB,componentBB;
component = new Window();
componentSB = new ScrollBarDecorator(component);
componentSB.display();
System.out.println("--------------------");
componentBB = new BlackBoarderDecorator(componentSB);
componentBB.display();
}
}
打印结果:
为构件增加滚动条!
显示窗体!
--------------------
为构件增加黑色边框!
为构件增加滚动条!
显示窗体!
要点:装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为。
6. 装饰者模式适用场景
在不影响其它对象情况下,以动态透明的方式给单个对象添加职责,需要动态给一个对象添加功能,这些功能可以在动态的被撤销。
需要注意的问题:
- 一个装饰者类的接口必须与被装饰者的接口一致;
- 尽量保持具体装饰者类作为一个“轻”类,也就是说不要把太多的逻辑和状态放到具体装饰者类去实现;
优先使用组合、聚合原则,少用继承。