装饰者模式

来源:互联网 发布:知不足而自省 编辑:程序博客网 时间:2024/06/06 03:16

一、定义:
动态地给一个对象添加一些额外的职责。就增加功能来说, 装饰模式相比生成子类更为灵活。
二、事例:
话说,小时候我学习不好,每次考试都是倒数前几名,刚开始还好,成绩单发了就发了,也不用家长签名,但后来,不知哪个xxx想出来个办法,每张成绩单都要家长签名,这可愁了我们这些学习差的孩子,签了挨家长打,不签挨学校大。但,上有政策,下有对策,正好我聪明机智,成绩单虽然是死的,但表达方式不一样,效果还是很大不同滴,比如我可以先说我的最高成绩或我排名进步多少等等,这样老爸及不会马上听到成绩就对我一通乱打了,哈哈。
三、代码:
首先我们要定义一个成绩单抽象类AbstractReport.class,规范成绩单的两个基本方法report()展示成绩和sign()家长签名。

/** * 成绩单抽象类 */public abstract class AbstractReport {    public abstract void report();//展示成绩    public abstract void sign(String name);//家长签名}

有了抽象类,我们就要定义一个实现类Report.class,实现抽象类的抽象方法。

/** * 四年级成绩单 */public class ForthReport extends AbstractReport{    @Override    public void report() {//展示成绩        // TODO Auto-generated method stub        System.out.println("尊敬的xxx家长");        System.out.println(".............");        System.out.println("语文87 数学 73 英语 67");        System.out.println(".............");    }    @Override    public void sign(String name) {//家长签名        // TODO Auto-generated method stub        System.out.println("家长签名为:"+name);    }}

成绩单有了,但我不敢直接拿给我爹看啊,我得装饰装饰,搞得好看一点,嘿嘿。所以,我先定义一个抽象装饰类AbstractDecorator.class。

/** * 抽象装饰者类,继承抽象成绩单类 */public abstract class AbstractDecorator extends AbstractReport{    private AbstractReport report;//成绩单    public AbstractDecorator(AbstractReport report){//构造函数,传入一个要装饰的成绩单        this.report=report;    }    @Override    public void report() {//展示成绩        // TODO Auto-generated method stub        this.report.report();//调用成绩单的report方法    }    @Override    public void sign(String name) {//家长签名        // TODO Auto-generated method stub        this.report.sign(name);//调用成绩单的sign方法    }}

有了抽象类,我们再来定义具体的实现类HighScoreDecorator.class

/** * 最高成绩修饰者类 */public class HighScoreDecorator extends AbstractDecorator{    public HighScoreDecorator(AbstractReport report) {        super(report);//调用父类的构造方法        // TODO Auto-generated constructor stub    }    @Override    public void report() {//展示成绩        // TODO Auto-generated method stub        reportHighScore();//报告成绩前,先报告最高成绩        super.report();//调用父类的报告方法    }    @Override    public void sign(String name) {//家长签名        // TODO Auto-generated method stub        super.sign(name);//调用父类的签名方法    }    private void reportHighScore(){//报告最高成绩        System.out.println("这次考试语文最高,87分,数学73分,英语67分");    }}

SortDecorator.class

/** * 排名装饰类 */public class SortDecorator extends AbstractDecorator{    public SortDecorator(AbstractReport report) {        super(report);//掉用父类的构造方法        // TODO Auto-generated constructor stub    }    @Override    public void report() {//展示成绩        // TODO Auto-generated method stub        sortReport();//报告成绩前,先报告班级排名        super.report();//调用父类的report方法    }    @Override    public void sign(String name) {//签名        // TODO Auto-generated method stub        super.sign(name);//调用父类的sign方法    }    private void sortReport(){//报告本次考试的班级排名        System.out.println("我这次考试的班级排名是:13");    }}

好了,一切准备就绪,我们来尝试一下把成绩单交给家长:

/** 1. 场景类 */public class Client {    public static void main(String[] args){        AbstractReport report;//成绩单对象        report=new ForthReport();//原装的成绩单        report=new HighScoreDecorator(report);//加了最高成绩修饰的成绩单        report=new SortDecorator(report);//再加上班级排名的成绩单        report.report();//报告成绩        report.sign("张三他爹");    }}

运行结果:
这里写图片描述
好了,老爸签名了,免了一顿毒打,开心玩游戏去喽。。。
四、角色:

装饰者模式,总结下来,至少要有四个角色:

1.Compoent抽象构件
Component是一个接口或者是抽象类, 就是定义我们最核心的对象, 也就是最原始的对象。如上例中的AbstractReport.class。(在装饰模式中, 必然有一个最基本、 最核心、 最原始的接口或抽象类充当Component抽象构件。)
2.ConcreteComponent 具体构件
ConcreteComponent是最核心、 最原始、 最基本的接口或抽象类的实现, 你要装饰的就是它。例如上例中的Report.class。
3. Decorator 抽象装饰角色
在它的属性里必然有一个private变量指向Component抽象构件。例如上例中的AbstractDecorator.class,里面有一个私有变量report,指向要装饰的成绩单。
4.具体装饰角色
实现抽象装饰角色中的方法,并且加入自己的装饰方法,真正把最原始基本的东西装饰成其它东西。
五、优点:
● 装饰类和被装饰类可以独立发展, 而不会相互耦合。 换句话说, Component类无须知道Decorator类, Decorator类是从外部来扩展Component类的功能, 而Decorator也不用知道具体的构件。
● 装饰模式是继承关系的一个替代方案。 我们看装饰类Decorator, 不管装饰多少层, 返回的对象还是Component, 实现的还是is-a的关系。(这个要抽象装饰类继承抽象被装饰类)
● 装饰模式可以动态地扩展一个实现类的功能。(这就是装饰者做的事情)
六、缺点:
对于装饰模式记住一点就足够了: 多层的装饰是比较复杂的。 为什么会复杂呢? 你想想看, 就像剥洋葱一样, 你剥到了最后才发现是最里层的装饰出现了问题, 想象一下工作量吧, 因此, 尽量减少装饰类的数量, 以便降低系统的复杂度。
七、使用场景:
● 需要扩展一个类的功能, 或给一个类增加附加功能。
● 需要动态地给一个对象增加功能, 这些功能可以再动态地撤销。
● 需要为一批的兄弟类进行改装或加装功能, 当然是首选装饰模式。
●装饰模式可以替代继承, 解决我们类膨胀的问题。(继承是静
态地给类增加功能, 而装饰模式则是动态地增加功能)

Demo

0 0
原创粉丝点击