装饰器模式
我们都知道装饰, 元旦, 圣诞节, 我们都需要装饰, 渲染节日气氛. . 所谓装饰, 就是在原来的基础上加东西.
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是对现有类的包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 我们通过下面的实例来演示装饰器模式的用法。其中,我们将把圣诞节的房间在原来的基础上装饰上了气球。
我们来看看UML图: 最开始有房子, 房子有平房, 楼房, 别墅, 我们会打扫房间.
/**
* 房子抽象类
*/
public interface IHouse {
void clean();
}
/**
* 平房
*/
public class Bungalow implements IHouse{
@Override
public void clean() {
// 打扫房间
}
}
/**
* 楼房
*/
public class HighRiseBuilding implements IHouse{
@Override
public void clean() {
// 打扫房间
}
}
/**
* 别墅
*/
public class Villa implements IHouse{
@Override
public void clean() {
// 打扫房间
}
}
这时, 遇到节假日, 比如:圣诞节, 元旦, 我们会装饰房间, 给房间布置气球等. 我们可以采用装饰器设计模式. 这时, 装饰的主体依然房子. 装饰就像是一个壳子, 套在房子的外面.
/**
* 房子抽象类
*/
public interface IHouse {
void clean();
}
/**
* 平房
*/
public class Bungalow implements IHouse{
@Override
public void clean() {
// 打扫房间
System.out.println("我是平房: 打扫房间");
}
}
/**
* 楼房
*/
public class HighRiseBuilding implements IHouse{
@Override
public void clean() {
// 打扫房间
System.out.println("我是楼房: 打扫房间");
}
}
/**
* 别墅
*/
public class Villa implements IHouse{
@Override
public void clean() {
// 打扫房间
System.out.println("我是别墅: 打扫房间");
}
}
/**
* 房间装饰器
*/
public abstract class DecoratorHouse implements IHouse {
// 被装饰的房子
protected IHouse decoratedHouse;
public DecoratorHouse(IHouse decoratedHouse) {
this.decoratedHouse = decoratedHouse;
}
}
public class BalloonDecoratorHouse extends DecoratorHouse {
public BalloonDecoratorHouse(IHouse decoratedHouse) {
super(decoratedHouse);
}
@Override
public void clean() {
// 打扫房间
super.decoratedHouse.clean();
ballonDecorate();
}
public void ballonDecorate() {
// 用气球装饰房间
System.out.println("用气球装饰房间, 好漂亮");
}
}
public class DecoratorPatternTest {
public static void main(String[] args) {
IHouse house = new Villa();
house.clean();
System.out.println("-------圣诞节到了, 装饰房间-------");
IHouse decoratorHouse = new BalloonDecoratorHouse(new Villa());
decoratorHouse.clean();
}
}
使用装饰器模式以后, 我们在不改变原有房子的基础上进行了扩展. 节假日, 就可以使用装饰类装饰房间, 如果节日过去了, 我们就继续使用原来的房子.
接下来, 我们来总结一些上面的案例. 首先, 我们有一个组件Component, 在这个组件里有一些自定义的功能. 通常这个组件Component是抽象的(接口或者抽象类) 然后, 抽象类会有一个具体的实现 ConcreteComponent, 除了实现组件Component的方法, 还可自定义方法. 第三, 我们现在想要对具体实现ConcreteComponent进行包装, 定义一个包装类 DecoratorComponent. 通常这个包装类是抽象的. 包装类也实现组件Component接口, 然后引入一个Component的具体的成员变量. 为什么要引入成员变量呢? 这个也很好理解, 我们的目标是包装的具体类. 第四, 定义一个具体的装饰器 DecoratorComponent, 再具体的装饰器中, 可以增加额外的方法. 比如在之前后者之后增加一些逻辑. 具体关系图如下:
代码实现如下:
/**
* 抽象功能
*/
public interface Component {
void operate();
}
/**
* 具体功能实现
*/
public class ConcreteComponent implements Component{
@Override
public void operate() {
// 实现具体的逻辑
System.out.println("具体实现的逻辑");
}
}
/**
* 用来装饰Component对象的类
*/
public abstract class DeceratorComponent implements Component{
// 指定装饰的对象
protected Component deceratedComponent;
public DeceratorComponent(Component deceratedComponent) {
this.deceratedComponent = deceratedComponent;
}
}
/**
* 具体的装饰类
*/
public class ConcreteDeceratorComponent extends DeceratorComponent {
public ConcreteDeceratorComponent(Component deceratedComponent) {
super(deceratedComponent);
}
@Override
public void operate() {
before();
super.deceratedComponent.operate();
after();
}
public void before(){
System.out.println("在原逻辑之前增加了逻辑");
}
public void after(){
System.out.println("在原逻辑之后增加了逻辑");
}
}
public class DeceratorTest {
public static void main(String[] args) {
Component concreteCom = new ConcreteComponent();
concreteCom.operate();
System.out.println("============");
DeceratorComponent decerator = new ConcreteDeceratorComponent(new ConcreteComponent());
decerator.operate();
}
}
运行结果:
具体实现的逻辑 ============ 在原逻辑之前增加了逻辑 具体实现的逻辑 在原逻辑之后增加了逻辑
设计模式的灵活应用. 假如当前具体类就只有一个. 我们就不需要定义抽象的Component了. 如何实现装饰模式呢? 那就让装饰器直接继承自原来的类就可以了:
以下情况可以考虑使用装饰器模式