装饰模式Decorator
是继承方案的一个替代方案,提供比继承更多的灵活性。
在不改变原类文件以及不使用继承的情况下,动态地将功能附加到对象上,从而实现动态拓展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
动态的给对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活
Component抽象被装饰者(应为接口)
ConcreteComponent是具体被装饰者
Decorator是抽象装饰者(是一个抽象类),子类为具体装饰者,每个装饰者都应该有一个实例变量用以保存某个Component的引用,因为装饰者本身也是Component的子类,从而包裹住了被装饰者,让其获得一些ConcreteComponent本来没有的功能,这就是装饰
Component约束了整个继承树的行为。比如说,如果Component代表人,即使通过装饰也不会使人变成别的动物,ConcreteComponent是Component的子类,实现了相应的方法,它充当了“被装饰者”的角色,可以是学生老师等校色
如果只有一个ConcreteComponent类而没有抽象的Component类,那么的Decorator的类可是时ConcreteComponent的一个子类,同理,若果只有一个ConcreteDecorator类,那么没有必要建立一个单独的Decorator类,可以把两者的责任合并成一个类
使用场景
当系统需要扩展一个类的功能,或者客户端需要动态的给一个对象添加功能,并且使用继承会很复杂时候。
IO中各种流的转换实际就是装饰者模式
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("filename")))
把类的装饰功能从类中一出去,有效的把类的核心职责与装饰功能区分开,去除相关类中重复的装饰逻辑
代码示例
一个人要穿各种衣服
Component类:(一般是一个接口)
限定继承树都是人且都有一个show方法
public interface Person {
void show();
}
ConcreteCompoent类:
被装饰者具体类
public class Student implements Person {
@Override
public void show() {
System.out.println("我是一个学生");
}
}
Decorater装饰者(一般是个抽象类,因为要有实例方法来接受这个类)
持有一个具体被装饰者实例
public abstract class Dec implements Person{
protected Person person;
public void Decorate(Person person){
this.person = person;
}
@Override
public void show() {
if (person != null) {
person.show();
}
}
}
ConcreteDecorator 具体装饰者类:
父类持有被装饰者引用,只重载方法,为其添加功能
public class DecoratorA extends Dec {
@Override
public void show() {
super.show();
System.out.println("穿裙子");
}
}
public class DecoratorB extends Dec {
@Override
public void show() {
super.show();
System.out.println("穿裤子");
}
}
测试
public class Test {
public static void main(String[] args) {
Person stud = new Student();
Dec decA = new DecoratorA();
Dec decB = new DecoratorB();
decA.Decorate(stud);
decB.Decorate(decA);
decB.show();
}
}
输出