结构型设计模式之装饰模式(Decorator)

设计模式之装饰模式

装饰模式简单来讲就是在不改变一个对象原有的逻辑的前提下,添加其他的逻辑。

举例说明:到了年尾了,公司要求每个都对自己的工作做一份报告,总结下一年的工作,首先是A同事总结:“我是XXXX,今年主要是完成指定的需求,巴拉巴拉…”,都是将自己做的一板一眼的讲出来,不带任何感情。领导听得都要快睡着了,虽然做了那么多,领导可能也觉得只是一个按部就班做事儿的人,没有什么出彩的地方,可能直接导致年终奖缩水(呜呜呜…)。
轮到B同事总结(实际上跟A同事做的事情一样多,但是说出来就不一样):“尊敬的各位领导/同事,我是XXXX,今年主要是完成指定的需求,通过完成不同的需求,让自己对业务更加熟悉和理解,在完成需求的同时,也对以前的一些逻辑做重构,降低后期的维护成本,balaba…”,在讲解了自己工作的同时,不忘总结,突出自己的价值,以及在工作中学到的一些东西等等,目的就是为了让领导觉得自己不仅能做事,还会做事,交代的是一,实际完成的是三,这样领导就会觉得这个小伙子很有前途,搞不好优秀员工就到手了。

以上是描述的一个现实中存在的一个情况,下面用代码描述出来:

/**
 * 年终总结
 */
public class EndOfYearConclusion {
    //A同事的年终总结
    static class AConclusion{

        //自我介绍
        public void introduce(){
            System.out.println("我是A....");
        }

        //报告内容(毫无技术含量)
        public void report(){
            System.out.println("今年主要是完成指定的需求,bababababa....");
        }
    }

    //B同事的年终总结
    static class BConclusion{

        //自我介绍
        public void introduce(){
            System.out.println("尊敬个各位领导/同事,我是B....,接下来是我的年终总结:");
        }

        //报告内容(经过精心整理)
        public void report(){
            System.out.println("今年主要是完成指定的需求,在完成需求的同时,也对以前的一些逻辑做重构,降低后期的维护成本,balaba...");
        }
    }

    public static void main(String[] args) {
        AConclusion aConclusion = new AConclusion();
        aConclusion.introduce();
        aConclusion.report();
        //领导听完A汇报
        System.out.println("我都快睡着了,A这个小伙子表现一般,年终奖降一点吧!");
        System.out.println("=========================================================================");
        BConclusion bConclusion = new BConclusion();
        bConclusion.introduce();
        bConclusion.report();
        //领导听完B汇报
        System.out.println("B这个小伙子做了这么多事情,超出了我的期望值,不错,今年的优秀员工就给他一个名额吧!");
    }
}

这段代码就是对以上场景的一个复现,从这里我们发现个问题,都是一样的工作,一个年终奖降了,一个成了优秀员工,怎么会这样呢?就是因为B对工作内容做了大量的修饰,突出了自己对公司的价值,让领导高看一眼(所以一味的老实是不行滴…)。

而B这种描述,就是对A的内容的一种修饰,从上面来看,A、B都有相同的接口,这里我们稍微重构下:

public class EndOfYearConclusion_01 {

    //年终总结接口
    interface Conclusion{
        //自我介绍
        public void introduce();

        //报告内容(毫无技术含量)
        public void report();
    }

    //A同事的年终总结
    static class AConclusion implements Conclusion{

        //自我介绍
        @Override
        public void introduce(){
            System.out.println("我是A....");
        }

        //报告内容(毫无技术含量)
        @Override
        public void report(){
            System.out.println("今年主要是完成指定的需求,bababababa....");
        }
    }

    //B同事的年终总结
    static class BConclusion implements Conclusion{

        //自我介绍
        @Override
        public void introduce(){
            System.out.println("尊敬个各位领导/同事,我是B....,接下来是我的年终总结:");
        }

        //报告内容(经过精心整理)
        @Override
        public void report(){
            System.out.println("今年主要是完成指定的需求,在完成需求的同时,也对以前的一些逻辑做重构,降低后期的维护成本,balaba...");
        }
    }

    //领导
    static class Leader{
        private Conclusion conclusion;

        public void listenReport(){
            conclusion.introduce();
            conclusion.report();
        }

        public Conclusion getConclusion() {
            return conclusion;
        }

        public void setConclusion(Conclusion conclusion) {
            this.conclusion = conclusion;
        }
    }

    public static void main(String[] args) {
        Leader leader = new Leader();
        leader.setConclusion(new AConclusion());
        leader.listenReport();
        //领导听完A汇报
        System.out.println("我都快睡着了,A这个小伙子表现一般,年终奖降一点吧!");
        System.out.println("=========================================================================");
        leader.setConclusion(new BConclusion());
        leader.listenReport();
        //领导听完B汇报
        System.out.println("B这个小伙子做了这么多事情,超出了我的期望值,不错,今年的优秀员工就给他一个名额吧!");
    }
}

这里让A、B都实现一个总结的接口,并实现两个方法。还添加了一个领导类,来接受到底是轮到哪个同事做年终总结,并可以通过调用listenReport()方法来表示听报告内容。

加入此时来一个经常做报告的C同事,他的报告比B更精彩,此时我们就要让C的总结实现接口类以及两个方法;
如果后面还有更精通作报告的D、E、F、…同事,那怎么办,每个人都要去实现这个接口类以及两个方法;(工作内容都相同,报告内容不同)

年终结束后,A有点丧气,觉得同样的工作,为什么待遇不同呢,于是就请教B或者其他,B告诉他,其实并不是他写得多好,而是借鉴了一些别人的,看别人是怎么写的,自己拿过来稍微的修改了一下。。。A听完后恍然大悟,我擦,居然还有这种操作,那明年我也可以这样搞一搞了(小开心一下^ - ^)。

就这样,来年,大家都对自己的报告做了修饰(实际都知道做的工作一样,就看谁的报告牛皮了,并且还做了备份,为下一年做准备),同时希望自己的主内容不变,来年只需要修改部分修饰信息,还可以继续用。那这个时候我们又要继续对代码进行新一轮的重构了:

public class EndOfYearConclusion_02 {

    //年终总结接口
    interface Conclusion{
        //自我介绍
        public void introduce();

        //报告内容(毫无技术含量)
        public void report();
    }

    //基本的年终总结模板
    static class BaseConclusion implements Conclusion{
        //自我介绍
        @Override
        public void introduce(){
            System.out.println("我是XXX");
        }

        //报告内容(毫无技术含量)
        @Override
        public void report(){
            System.out.println("今年主要是完成指定的需求");
        }
    }

    //这是一个抽象类,主要是被子类继承,并且自身持有了一个总结的引用
    static abstract class AbstractConclusion implements Conclusion{
        private Conclusion conclusion;

        public AbstractConclusion(Conclusion conclusion){
            this.conclusion = conclusion;
        }

        public Conclusion getConclusion() {
            return conclusion;
        }
    }

    //A同事的年终总结,
    static class AConclusion extends AbstractConclusion{

        public AConclusion(Conclusion conclusion) {
            super(conclusion);
        }

        @Override
        public void introduce(){
            System.out.println("尊敬的各位领导/同事:");
            super.getConclusion().introduce();
        }

        @Override
        public void report(){
            super.getConclusion().report();
            System.out.println("在完成需求的同时,也对以前的一些逻辑做重构,降低后期的维护成本");
        }
    }

    //B同事的年终总结
    static class BConclusion extends AbstractConclusion{

        public BConclusion(Conclusion conclusion) {
            super(conclusion);
        }

        @Override
        public void introduce(){
            super.getConclusion().introduce();
            System.out.println("接下来是我的年终总结:");
        }

        @Override
        public void report(){
            super.getConclusion().report();
            System.out.println("在今年的工作中,对自己有了更高的要求,主要体现在对系统的性能做了优化,等等...");
        }
    }

    //领导
    static class Leader{
        private Conclusion conclusion;

        public void listenReport(){
            conclusion.introduce();
            conclusion.report();
        }

        public Conclusion getConclusion() {
            return conclusion;
        }

        public void setConclusion(Conclusion conclusion) {
            this.conclusion = conclusion;
        }
    }

    public static void main(String[] args) {
        BaseConclusion baseConclusion = new BaseConclusion();
        Leader leader = new Leader();
        leader.setConclusion(new AConclusion(baseConclusion));
        leader.listenReport();
        System.out.println("今年A这个小伙子进步很大呀,有前途,加点年终奖...");
        System.out.println("===================================================");
        leader.setConclusion(new BConclusion(baseConclusion));
        leader.listenReport();
        System.out.println("今年B这个小伙子也很不错,居然超出了预期,继续保留优秀员工...");
        System.out.println("===============================================================");
        leader.setConclusion(new BConclusion(new AConclusion(baseConclusion)));
        leader.listenReport();
        System.out.println("哟呵,这个小伙子更不错啊,居然A和B能做的事情他都有做,很好,给他优秀员工,加年终,加薪...");
    }
}

以上就是重构后的代码,通过代码我们复现了一个写年终总结的一个大概情形,就是基本内容都一样的时候,可以通过相互借鉴的方式,使得自己的总结报告更加出彩,凸显自己的能力,让领导刮目相看。

总结:

上面重构后的代码结构,符合了装饰模式的定义:动态的给一个对象添加一些额外的职责。(就增加功能来说,装饰模式相比生成子类更加灵活)

装饰模式的优点:
被装饰的类和装饰类可以独立发展自己的逻辑,互不影响;
而且有点类似于代理模式(或者可以认为是一个简单的代理模式的实现);

装饰模式的缺点:
美中不足的是,装饰模式一层套一层,类似与洋葱,如果出现问题,那么势必要一层一层的剥开,这样找起问题来相当麻烦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值