您的位置:首页 > 编程语言 > Java开发

设计模式11-装饰模式

2017-08-15 16:34 225 查看
       装饰模式顾名思意,就是对原对象进行修饰。就像给房子装修一样,可以让房子好看。在java里面使用装饰模式,可以让对象的功能更加的好看,表达委婉。
      假如有这样的一个场景,我们小时候考试,成绩考的不好,老师需要拿成绩单回去,给家长签字,由于成绩不好,根本不敢拿给家长看,更别说签名了。这时候如果我们能委婉的表达我们的成绩,说不定家长一高兴就签名了。看下面的类图:



1,学生抽象类成绩如下:
package com.jack.decoratemodel;

/**
* Created by jack on 2017/8/7.
* 抽象类,学生成绩
*/
public abstract class SchoolReport {
/**
* 成绩单,主要展示的就是成绩情况
*/
public abstract void report();

/**
* 成绩单要家长签名
*/
public abstract void sign(String name);
}


2,具体成绩如下:
package com.jack.decoratemodel;

/**
* Created by jack on 2017/8/7.
* 四年级成绩单
*/
public class FouthGradeSchoolReport extends SchoolReport{
/**
* 成绩单
*/
@Override
public void report() {
//成绩单的输出格式
System.out.println("尊敬的xx家长:");
System.out.println(".........................");
System.out.println("语文:59,数学:49,体育:60,英语48");
System.out.println(" 家长签名: ");
}

/**
* 家长签名
*/
@Override
public void sign(String name) {
System.out.println("家长签名为:"+name);
}
}


3,抽象装饰类如下:

package com.jack.decoratemodel;

/**
* Created by jack on 2017/8/15.
* 修饰的抽象类
*/
public abstract class Decorator extends SchoolReport{
/**
* 成绩单
*/
private SchoolReport sr;

/**
* 构造函数传递成绩单过来
* @param sr
*/
public Decorator(SchoolReport sr) {
this.sr = sr;
}

/**
* 成绩单还是需要看的
*/
@Override
public void report() {
this.sr.report();
}
/**
* 成绩单看完还是需要签名的
* @param name
*/
@Override
public void sign(String name) {
this.sr.sign(name);
}
}

      装饰类还是把动作的执行委托给需要装饰的对象,Decorator抽象类的目的很简单,就是让子类来封装SchoolReport的子类

4,最高成绩修饰代码如下:
package com.jack.decoratemodel;

/**
* Created by jack on 2017/8/15.
* 最高成绩修饰
*/
public class HighScoreDecorator extends Decorator{
/**
* 构造函数传递成绩单过来
*
* @param sr
*/
public HighScoreDecorator(SchoolReport sr) {
super(sr);
}

/**
* 汇报最高成绩
*/
private void reportHighScore(){
System.out.println("这次语文最高是75,数学是80,英语是70");
}

/**
* 老爸看成绩之前,先看下最高成绩
*/
@Override
public void report() {
this.reportHighScore();
super.report();
}
}

重写report方法,先调用具体装饰的装饰方法reportHighScore,然后再调用具体构建的方法

5,排名情况修饰代码如下:
package com.jack.decoratemodel;

/**
* Created by jack on 2017/8/15.
* 排名情况修饰
*/
public class SortDecorator extends Decorator{
/**
* 构造函数传递成绩单过来
*
* @param sr
*/
public SortDecorator(SchoolReport sr) {
super(sr);
}

/**
* 告诉排名情况
*/
private void reportSort(){
System.out.println("我是排名22");
}

/**
* 看完成绩后,告诉排名情况
*/
@Override
public void report() {
super.report();
this.reportSort();
}
}


6,测试类
    老爸查看成绩单,代码如下:
package com.jack.decoratemodel;

/**
* Created by jack on 2017/8/15.
* 老爸查看成绩单
*/
public class FatherMain {
public static void main(String[] args) {
//把成绩单拿过来
SchoolReport sr = null;
//原装的成绩单
sr = new FouthGradeSchoolReport();
//加了高分说明的成绩单
sr = new HighScoreDecorator(sr);
//加了成绩排名的成绩单
sr = new SortDecorator(sr);
//看成绩单
sr.report();
sr.sign("jack");
}
}


      上面就是一个简单的装饰模式的简单例子。如果还需要增加其他的修饰条件,也非常容易,只要实现Decorator类就可以了。

装饰模式定义:

        装饰模式:动态地给一个对象添加一些而外的职责。就功能来说,装饰模式相比生成子类更为灵活。

   装饰模式的通用类图如下:



再类图中有四个角色
Component抽象构建:Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象,入上面的成绩单。再装饰模式中,必然有一个最基本,最核心,最原始的接口或抽象类充当Component抽象构建。

ConcreteComponent具体构件:ConcreteComponent是最核心最原始,最基本的接口或抽象类的实现,你要装饰的就是它。

Decorator装饰角色:一般是一个抽象类,实现接口或抽象方法,它里面可不一定有抽象的方法,再它的属性里必然有一个private变量指向Component抽象构建。

具体装饰角色:ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要把最核心的,最原始的,最基本的东西装饰成其他的东西。上面的例子就是把一个比较平庸的成绩单装饰成一个马马虎虎家长认可的成绩当。
    

装饰模式的优点:

1,装饰类和被装饰类可以独立发展,而不会相互耦合。也就是说Component类无需知道Decorator类,Decorator类是从外部扩展Component类的功能,而Decorator也不用知道具体的构件。
2,装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
3,装饰模式可以动态地扩展一个实现类的功能。

装饰模式的缺点:
      对于装饰模式记住一点就够了:多层的装饰是比较复杂的,因此减少装饰类的数量,以便降低系统的复杂度。

使用场景:
1,需要扩展一个类的功能,或给一个类增加附加功能
2,需要动态地给一个对象增加功能,这些功能可以再动态的撤销
3,需要为一批的兄弟类进行改装或加装功能,当然首选装饰模式

代码地址:https://github.com/wj903829182/springboot/tree/master/designpattern
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息