装饰器模式说白了很简单,先来一张图
Component:组件对象的接口,可以给这些对象动态的添加职责;
ConcreteComponent:具体的组件对象,实现了组件接口。该对象通常就是被装饰器装饰的原始对象,可以给这个对象添加职责;
Decorator:所有装饰器的父类,需要定义一个与组件接口一致的接口(主要是为了实现装饰器功能的复用,即具体的装饰器A可以装饰另外一个具体的装饰器B,因为装饰器类也是一个Component),并持有一个Component对象,该对象其实就是被装饰的对象。如果不继承组件接口类,则只能为某个组件添加单一的功能,即装饰器对象不能在装饰其他的装饰器对象。
ConcreteDecorator:具体的装饰器类,实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另外一个具体的装饰器对象。
——————————华丽的分割线————————————
别看上面东西挺多,其实说白了也没几句话,就是给原来的东西套上一个壳,没必要定的那么死,这个一定要接口那个一定要实现类什么的,我举个例子
public class Person{
//吃饭方法
public void eat(){
System.out.println("开始吃饭……吃完了");
}
}
public class Japanese{
private Person person;
public Japanaese(Person p){
person=p;
}
//日本人吃饭
public void JapaneseEating(){
System.out.println("一大大可一骂死(我开动了……)");
p.eat();
}
}
说白了装饰器模式就是拓展原有的类,让他实现更多的功能
那么问题来了,我用继承的方法不是也能做到上面的效果么?我重写一个Japanese类继承Person类再重写一下eat方法不也可以?确实上面这个例子是可以,但是想一想你继承通常是用来干什么的,你继承一般都在哪用。我认为继承是需要统一行为的类的时候用的,子类不能有父类没有的特性。我现在再举一个例子
//装备飞行器的人
class PersonWithAerocraft{
private Person self;
public PersonWithAerocraft(Person p){
self=p;
}
public void eat(){ //你也可以起别的名字
System.out.println("我穿着飞行器,但我一样可以吃饭");
self.eat();
}
public void fly(){
System.out.println("我穿着飞行器在飞!")
}
}
你看,现在这个人能飞了。你还能用继承或者实现接口来满足这个情况么?由此你也可以知道,装饰器的功能之一就是描述事物的状态(其实这也是我刚刚才想到的……)。比如上面这个穿了飞行器的人,这个时候他是可以飞的,你总不能给Person类加个方法让全人类都能飞吧。更扯得是你想一下,如果你的Person是个接口呢?在实际项目中你根本不能轻易的去改这些接口,因为你一改接口,所有实现接口的类都要重新修改,一个两个文件还好说,如果项目比较大,成百上千个类需要你去改那怎么办。所以很多时候你需要额外添加一个装饰器类来拓展你原有类的功能。当然,你也可以做一个装饰器接口。
继承不能当成装饰器来用,装饰器也同样不能当作继承,我们不说装饰器不能像继承那样父类 a=new 子类()这种形式创建,你要想实现原本类方法还得自己重新写,比如人能吃喝拉撒睡,戴着飞行器的人也能,但你想让装饰器类实现这个方法就得自己重新再写。当然你也可以直接用xxx.person.xxxx(),就是对其他人不怎么友好
你看,说了半天其实上面都是些废话。实际上这装饰器就是一个类里有那么一个成员变量,然后再利用这个成员变量提供几个自己需要用的方法。优点就是不用修改原有代码就可以添加功能