设计模式之装饰者模式

罪恶的成绩单

故事从四年级的小明期末考试完后,拿着成绩单回家找老爸签字说起,我们小明的成绩是这样的:语文:12分 数学22分。小明路上这个忐忑啊,这点成绩家长能签字吗,不打死我就挺好的了。小明猜的没错,他爸的确会打他!看类图如下:

代码如下:

抽象成绩单

public abstract class SchoolReport {
    //成绩单主要展示的就是你的成绩情况
    public abstract void report();
    //成绩单要家长签字,这个是最要命的
    public abstract void sign();
}

四年级成绩单

public class FouthGradeSchoolReport extends SchoolReport {
    //我的成绩单
    public void report() {
        //成绩单的格式是这个样子的
        System.out.println("尊敬的XXX家长:");
        System.out.println("    ......");

        System.out.println(" 语文 12  数学22 ");
        System.out.println("    .......");
        System.out.println("    家长签名:   ");
    }
        //家长签名
        public void sign(String name) {
             System.out.println("家长签名为:"+name);
        }
}

老爸查看成绩单

public class Father {
    public static void main(String[] args) {
        //把成绩单拿过来
        SchoolReport sr = new FouthGradeSchoolReport();
        //看成绩单
        sr.report();
        //签名?考这么点成绩,没打你就挺好的了,还想签名!
    }
}

运行结果如下:

尊敬的XXX家长:
......

语文 62 数学65 体育 98 自然 63
.......

家长签名:

其实我们小明考的挺好,只是没有修饰

其实小明考的非常好,这次考试,语文最高分13分 数学最高分22分, 小明班级排名第一!所以我们小明死脑筋,不会装饰一下成绩单,下面我们来装饰一下,类图如下:

修饰的抽象类

public abstract class Decorator extends SchoolReport{
    //首先我要知道是哪个成绩单
    private SchoolReport sr;
    //构造函数,传递成绩单过来
    public Decorator(SchoolReport sr){
        this.sr = sr;
    }
    //成绩单还是要被看到的
    public void report(){
        this.sr.report();
    }
    //看完还是要签名的
    public void sign(String name){
        this.sr.sign(name);
    }
}

看到没,装饰类还是把动作的执行委托给需要装饰的对象,Decorator抽象类的目的很简单,就是要让子类来封装SchoolReport的子类,怎么封装?重写report方法!先看HighScoreDecorator实现类。

最高成绩修饰

public class HighScoreDecorator extends Decorator {
    //构造函数
    public HighScoreDecorator(SchoolReport sr){
        super(sr);
    }
    //我要汇报最高成绩
    private void reportHighScore(){ 
        System.out.println("这次考试语文最高是75,数学是78,自然是80");
    }
    //我要在老爸看成绩单前告诉他最高成绩,否则等他一看,就抡起扫帚揍我,我哪里还有机会说啊
    @Override
    public void report(){
        this.reportHighScore();
        super.report();
    }
}

重写了report方法,先调用具体装饰类的装饰方法reportHighScore,然后再调用具体构件的方法.
我们再来看怎么汇报学校排序情况SortDecorator代码

排名情况修饰

public class SortDecorator extends Decorator {
    //构造函数
    public SortDecorator(SchoolReport sr){  
        super(sr);
    }
        //告诉老爸学校的排名情况
    private void reportSort(){ 
        System.out.println("我是排名第38名...");
    }
        //老爸看完成绩单后再告诉他,加强作用
    @Override
    public void report(){
        super.report();
        this.reportSort();
    }
}

我准备好了这两个强力的修饰工具,然后就“毫不畏惧”地把成绩单交给老爸,看看老爸怎么看成绩单的.

老爸查看修饰后的成绩单

public class Father {
    public static void main(String[] args) {
        //把成绩单拿过来
        SchoolReport sr;
        //原装的成绩单
        sr = new FouthGradeSchoolReport();
        //加了最高分说明的成绩单
        sr = new HighScoreDecorator(sr);
        //又加了成绩排名的说明
        sr = new SortDecorator(sr);
        //看成绩单
        sr.report();
        //然后老爸一看,很开心,就签名了
        sr.sign("老三");  //我叫小三,老爸当然叫老三
    }
}

老爸一看成绩单,听我这么一说,非常开心,赶紧签名。
想想看,如果我还要增加其他的修饰条件,是不是就非常容易了,只要实现Decorator类就可以了!这就是装饰模式。

装饰模式的优点和缺点

优点

● 装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。

● 装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。

● 装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此。

缺点

对于装饰模式记住一点就足够了:多层的装饰是比较复杂的。为什么会复杂呢?你想想看,就像剥洋葱一样,你剥到了最后才发现是最里层的装饰出现了问题,想象一下工作量 吧,因此,尽量减少装饰类的数量,以便降低系统的复杂度。

结尾

好吧就讲到这里吧,点击下载代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序编织梦想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值