装饰器模式
在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。
定义
装饰器模式(Decorator Pattern)属于对象结构型模式。在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)。
优点
- 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
- 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
- 装饰器模式完全遵守开闭原则
缺点
装饰模式会增加许多子类,过度使用会增加程序得复杂性。
模式结构
- 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰(Concrete Decorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
应用场景
- 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
- 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时。
示例
开发商有很多房子,我买了其中一个,现在要对它进行装饰。
房子
package com.designpattern.decorator.interfaces;
public abstract class House {
public House() {
}
public abstract void description();
}
我自己的房子
package com.designpattern.decorator.department;
import com.designpattern.decorator.interfaces.House;
public class SweetHouse extends House {
@Override
public void description() {
System.out.println(this);
}
@Override
public String toString() {
return "Sweet House.";
}
}
装修的时候我自己的房子是不能动的,如果添加一个子类来继承的话,相当于我又买了一套新的房子,这是不现实的。
装修公司
于是,我找了一家装修公司,以房子为基础,在房子上添加各种东西。
package com.designpattern.decorator.interfaces;
public abstract class Decorator extends House {
private House house;//装修公司以房子为基础,在房子的基础上增加装饰
public Decorator(House house) {
this.house = house;
}
@Override
public void description(){
house.description();
}
@Override
public String toString() {
return "Decorator{" + "house=" + house + '}';
}
}
门
第一天装门。
package com.designpattern.decorator.decorator;
import com.designpattern.decorator.interfaces.Decorator;
import com.designpattern.decorator.interfaces.House;
public class Door extends Decorator {
public Door(House house) {
super(house);
}
@Override
public void description() {
super.description();
System.out.println(this);
}
@Override
public String toString() {
return "Add Door.";
}
}
窗户
第二天装窗户
package com.designpattern.decorator.decorator;
import com.designpattern.decorator.interfaces.Decorator;
import com.designpattern.decorator.interfaces.House;
public class Window extends Decorator {
public Window(House house) {
super(house);
}
@Override
public void description() {
super.description();
System.out.println(this);
}
@Override
public String toString() {
return "Add Window";
}
}
灯
第三天装灯
package com.designpattern.decorator.decorator;
import com.designpattern.decorator.interfaces.Decorator;
import com.designpattern.decorator.interfaces.House;
public class Light extends Decorator {
public Light(House house) {
super(house);
}
@Override
public void description() {
super.description();
System.out.println(this);
}
@Override
public String toString() {
return "Add Light";
}
}
查看进度
package com.designpattern.decorator;
import com.designpattern.decorator.decorator.Door;
import com.designpattern.decorator.decorator.Light;
import com.designpattern.decorator.decorator.Window;
import com.designpattern.decorator.department.SweetHouse;
import com.designpattern.decorator.interfaces.House;
public class Application {
public static void main(String[] args) {
//创建一个房子
System.out.println("================================This is a new house.===================================");
House house = new SweetHouse();
house.description();
//装上门
System.out.println("================================Add door to the house.=================================");
house = new Door(house);
house.description();
//装上窗子
System.out.println("================================Add window to the house.===============================");
house = new Window(house);
house.description();
//装上灯
System.out.println("================================Add light to the house.================================");
house = new Light(house);
house.description();
}
}
输出:
================================This is a new house.===================================
Sweet House.
================================Add door to the house.=================================
Sweet House.
Add Door.
================================Add window to the house.===============================
Sweet House.
Add Door.
Add Window
================================Add light to the house.================================
Sweet House.
Add Door.
Add Window
Add Light
装修完成。
结论
从上面的例子上来看,如果不断使用子类继承的方式的话,每一个子类都得包含父类的全部信息,并且各个子类呈链条式存在。但是如果采取装饰器模式的话,各个新增加的属性或者方法完全独立存在,顺序不分先后。除了最上面的抽象父类之类,各个类之间不存在任何交叉和冲突。
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
简单来说,就是现在有一个对象,需要添加新的属性或者方法。一般来说,我们可以实现他的子类来增加新的属性,但是需要增加的属性越来越多的时候,随之而来的子类也会越来越多。装饰器就是为了解决这一问题而存在的。
在 Java语言中,装饰器模式最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。