一、引
面向对象编程就是一个不断的抽象的过程,经过前面几个模式和原则的认识,相信会对面向对象有了进一步的理解,在编写代码中我会需要时刻提醒自己对需求进行合理的抽象。不同的模式是为了解决不同的情况,但终究是依靠面向对象编程中的几个特性封装、继承、多态,都是为了达到可维护、可扩展、可复用、灵活性好,而这一次将要提到的装饰模式(Decorator),就是针对需要不断在已有的功能职责中添加新的职责的情况。
二、问题
现在提出,我们需要设计一个试衣间的小程序,即人能够穿搭各种服饰,这种情况你会如何设计程序?
三、理解
通过之前的学习,我们知道我们要按照抽象分离的角度去写这个程序,所以我们会将人和服饰抽象出来,然后各种不同的服饰类别,如帽子、衣服、裤子继承服饰类,然后人类通过操作具体的服饰类完成程序的功能。这种做法确实是利用了面向对象思想去设计的,但“用了”并不代表用好了,这种做法还是存在考虑不周的情况,比如我在出程序调用服饰类,这意味着没有进行合适的封装,就像你当着大庭观众试衣服一般。那么我们进行封装,使用一个类似工厂类对人进行服饰的装扮,但是如果我需要在已经穿有的衣服的基础之上添加或者更换衣服,是不是需要修改工厂类,这样可能会引起不必要的麻烦,并不是一种好的做法,而装饰模式为我们解决了这类问题。
装饰模式(Decorator),动态的给一些对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。使得我们能够将所需的功能按照正确的顺序串联起来进行控制。装饰模式的结构如下:
Component是定义一个对象接口,可以给这些对象动态的添加职责。ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责,Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对Component来说,是无需知道Decorator的存在,至于ConcreteComponent就是具体的装饰对象,起到了给Component添加职责的功能。当然,有时候要学会活学活用,就比如试衣服的例子中,我们只有人(ConcreteComponent),而没有Component,所以这个时候,我们灵活的将Decorator继承了人(ConcreteComponent)就行了。
四、实现
public abstract class Component {
public abstract void Operation();
}
public abstract class Decorator extends Component {
private Component component;
public void SetComponent(Component component) {
this.component = component;
}
@Override
public void Operation() {
if(component != null) {
component.Operation();
}
}
}
public class ConcreteComponent extends Component {
@Override
public void Operation() {
// 具体操作,即原有的核心功能操作
}
}
public class ConcreteDecoratorA extends Decorator {
private String addState;
@Override
public void Operation() {
super.Operation();//需要先执行原来的功能,再执行以后的操作
addState = "New State";
//A的具体操作
}
}
public class ConcreteDecoratorB extends Decorator {
private String addState;
@Override
public void Operation() {
super.Operation();//需要先执行原来的功能,再执行以后的操作
addState = "New State";
//B的具体操作
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConcreteComponent concreteComponent = new ConcreteComponent();
ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA();
ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB();
concreteDecoratorA.SetComponent(concreteComponent);
concreteDecoratorB.SetComponent(concreteDecoratorA);
concreteDecoratorB.Operation();
}
}
装饰模式利用SetComponent来对对象进行包装,这样每个装饰对象的实现就和如何使用这个装饰对象分开,每个装饰对象只关心自己的功能,不用关心如何被添加到对象链当中。