装饰器模式
装饰器模式是一个比较常见的模式,其主要是动态的给一个对象添加一些额外的职责。但从给对象增加职责来说,使用继承也能够实现,但是正如《head first大话设计模式》中那样,单纯的继承会造成“类爆炸”的问题,同时继承也不够灵活,很难做到对扩展开放,对修改关闭。所以,从这个角度来说,装饰模式相比生成子类来说更为灵活。
装饰模式的类图结构如下:
在类图中,包含四个部分的角色,Component抽象组件,它是一个接口或者抽象类,定义最核心的对象,是所有类的超类;ConcreateComponent:具体的构件,是最核心,最原始,最基本的接口或者抽象类的实现,我们要装饰的对象就是它;Decorator:装饰角色,一般是一个抽象类,实现接口或者抽象方法,它里边不一定有抽象方法,但是一定有一个private变量指向Component抽象构件;具体装饰角色ConcreateDecorator1和ConcreateDecorator2是两个具体的装饰类,把最核心,最原始,最基本的东西装饰成其他的东西。
首先,来看一个例子。我们购买一套别墅,然后分别对别墅进行装修(增加餐厅、卧室等)。其代码实现如下:
public class Test {
public static void main(String[] args) {
//拥有一个餐厅的别墅
Room room = new VillasHouseWithDailingRoom(new VillasHouse());
System.out.println(room.getCost());
//拥有一个餐厅,一个卧室的别墅
room = new VillasHouseWithBedRoom(room);
System.out.println(room.getCost());
//拥有一个餐厅,两个卧室的别墅
room = new VillasHouseWithBedRoom(room);
System.out.println(room.getCost());
}
}
/**
* 房子的抽象类
*/
abstract class Room {
protected abstract int getCost();
}
/**
* 抽象类,表示空房子
*/
abstract class House extends Room {
}
/**
* 具有不同房间的房子
*/
abstract class RoomHouse extends Room {
private Room room;
public RoomHouse(Room room) {
this.room = room;
}
@Override
protected int getCost() {
return room.getCost();
}
}
/**
* 空别墅,100万一套
*/
class VillasHouse extends House {
@Override
protected int getCost() {
return 100;
}
}
/**
* 具有一个餐厅的别墅,装修一个餐厅10万
*/
class VillasHouseWithDailingRoom extends RoomHouse {
public VillasHouseWithDailingRoom(Room room) {
super(room);
}
@Override
protected int getCost() {
return super.getCost() + 10;
}
}
/**
* 具有一个卧室的别墅,装修一个卧室20万
*/
class VillasHouseWithBedRoom extends RoomHouse {
public VillasHouseWithBedRoom(Room room) {
super(room);
}
@Override
protected int getCost() {
return super.getCost() + 20;
}
}
其类图结构如下:
我们首先定义了一个超类Room类,表示所有房子,然后定义了一个VillasHouse类继承了Room类,VallasHouse就是我们的ConcreateComponent,就是我们需要装饰的对象;接着定义了一个抽象类(装饰器类):RoomHouse,表示具有某种房间的房子,接着定义了两个具体的装饰器类:VillasHouseWithDailingRoom和VillasHouseWithBedRoom。最后在Test(Client)类中对VillasHouse进行了装饰,使得VallasHouse具有了餐厅和卧室(给VallasHouse增加了新的功能)。
装饰器模式的优点
装饰类和被装饰类可以独立发展而不会相互耦合;
装饰模式是继承关系的一个替代方案,我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
装饰器模式可以动态的扩展一个类的功能。
装饰器模式的使用场景
需要扩展一个类的功能或者给一个类增加附加功能;
需要动态的给一个对象增加功能,这些功能可以再动态的撤销;
需要为一批发兄弟类进行改装或者加装功能。