1.什么是装饰模式
装饰模式是一种用于替代继承的技术。它无需定义子类却可以给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。
举个栗子:一张照片,不改变照片本身,给它增加一个相框,使他增加防潮的功能,这就是装饰模式。
装饰模式是一种对象结构型模式,他以对客户透明的方式动态的给一个对象附加上更多的责任,可以在不需要创建更多子类的情况下让对象的功能得以扩展。
2.装饰模式的结构
(1)Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构建中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
(2)ConcreteComponent(具体构件):它是抽象构件的子类,用于定义具体的构建对象,实现了在抽象构建中声明的方法,装饰类可以给它增加额外的职责。
(3)Decorator(抽象装饰类):他也是抽象构件的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
(4)ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,他可以调用在抽象装饰类中定义的方法,并可以增加新的方法用于扩充对象的行为。
3.装饰模式的实现
(1)抽象构件类的典型代码:
package controller.decoratorModule;
/**
* 抽象构件类
*/
public abstract class Component {
public abstract void operation();
}
(2)具体构件
package controller.decoratorModule;
/**
* 具体构件
*/
public class ConcreteComponent extends Component {
@Override
public void operation() {
//基本功能实现
}
}
(3)抽象装饰类
package controller.decoratorModule;
/**
* 抽象装饰类
*/
public class Decorator extends Component {
private Component component;//维持一个对抽象构件对象的引用
//注入一个抽象构件类型的对象
public Decorator(Component component){
this.component = component;
}
@Override
public void operation() {
component.operation();//调用原有业务方法
}
}
(4)具体装饰类
package controller.decoratorModule;
/**
* 具体装饰类
*/
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operation(){
super.operation();//调用原有业务方法
addBehavior();//调用新增业务方法
}
//新增业务方法
public void addBehavior() {
}
}
4.装饰模式实例——图形界面新增一些效果:滚动的窗体,带黑边的文本框等
(1)抽象构件类
package controller.decoratorModuleVisual;
/**
* 抽象构件类
*/
public abstract class Component {
public abstract void display();
}
(2)窗体类,充当具体构建类
package controller.decoratorModuleVisual;
/**
* 窗体类,充当具体构建类
*/
public class Window extends Component {
@Override
public void display() {
System.out.println("显示窗体!");
}
}
(3)文本框类,充当具体构建类
package controller.decoratorModuleVisual;
/**
* 文本框类,充当具体构建类
*/
public class TextBox extends Component {
@Override
public void display() {
System.out.println("显示文本框!");
}
}
(4)列表框类
package controller.decoratorModuleVisual;
/**
* 列表框类
*/
public class ListBox extends Component {
@Override
public void display() {
System.out.println("显示列表框!");
}
}
(5)构件装饰类,充当抽象装饰类
package controller.decoratorModuleVisual;
/**
* 构件装饰类,充当抽象装饰类
*/
public class ComponentDecorator extends Component {
private Component component;//维持一个对抽象构件对象的引用
public ComponentDecorator(Component component){
this.component = component;
}
@Override
public void display() {
component.display();
}
}
(6)滚动条装饰类,充当具体装饰类
package controller.decoratorModuleVisual;
/**
* 滚动条装饰类,充当具体装饰类
*/
public class ScrollBarDecorator extends ComponentDecorator {
public ScrollBarDecorator(Component component) {
super(component);
}
public void display(){
setScrollBar();
super.display();
}
private void setScrollBar() {
System.out.println("为构件增加滚动条!");
}
}
(7)黑色边框装饰类,充当具体装饰类
package controller.decoratorModuleVisual;
/**
* 黑色边框装饰类,充当具体装饰类
*/
public class BlackBorderDecorator extends ComponentDecorator {
public BlackBorderDecorator(Component component) {
super(component);
}
public void display(){
setBlackBorder();
super.display();
}
private void setBlackBorder() {
System.out.println("为构件增加黑色边框!");
}
}
(8)测试
package controller.decoratorModuleVisual;
public class Client {
public static void main(String[] args) {
Component component,componentSB,componentBB;//使用抽象构件定义对象
component = new Window();//创建具体构件对象
componentSB = new ScrollBarDecorator(component);//创建装饰后的构建对象
componentBB = new BlackBorderDecorator(componentSB);//二次装饰
componentBB.display();
}
}
(9)测试结果
5.透明装饰模式和半透明装饰模式
一般情况装饰模式对客户端是透明的。
透明的代码如上。
但是有些新增行为可能需要单独被调用,因此客户端需要能知道,这就是半透明。
Component component_o;//抽象构件类型
component_o = new ConcreteComponent();
component_o.operation();
ConcreteDecorator component_d;//具体装饰类型
component_d = new ConcreteDecorator(component_o);
component_d.operation();
component_d.addBehavior();//单独调用新增业务
6.装饰模式优缺点
优:
(1)拓展对象功能更灵活
(2)对一个对象多次装饰
(3)具体构建类和装饰类独立
缺:
(1)会有很多小对象,占用资源
(2)更容易出错
7.装饰模式使用环境
(1)不影响其他对象的情况下动态,透明的给单个对象添加职责
(2)不能采用继承时用装饰。
不能采用继承的两种情况:
(1)存在大量独立的扩展,子类数量会剧烈增加
(2)被final修饰了