设计模式之装饰器模式

装饰器模式,顾名思义就是在一个原有的类的上增加额外的功能,前提是不能修改类的代码。其实为一个类增加功能,可以用继承来实现,但是这样会使得类的数量层爆炸式增长,每增加一个功能,都会通过继承生成一个新类。我们使用代码来验证上面的结论:
 
类Student具有学习的功能,
public class Student {
    public void study(){
        System.out.println("我是一个学生,学习是我的天职。");
    }
}
现在我想给它添加踢足球的功能,根据开闭原则,我们是不允许修改Student的方法的,因此我们创建出一个新类,继承于Student,类名为FootbalStudent,代码如下:
public class FootballStudent extends Student{
    public void playFootball(){
        System.out.println("我喜欢踢足球。");
    }
}
 
如果我想给Student添加打篮球的功能,则创建一个BasketballStudent,继承自Student,增加一个playBasketball方法,代码如下所示:
public class BasketballStudent extends Student{
    public void playBasketball(){
        System.out.println("我喜欢打篮球");
    }
}
这时我们有了三个类,分别是只有学习功能的Student,具备学习和踢足球的FootbalStudent类以及具备学习和打篮球的BasketballStudent类。如果我需要一个既具备学习又能够打篮球和踢足球的类时,我又要创建一个FootballBasketballStudent类,这样会导致我项目中类的数量暴涨。而装饰器模式就是专门解决上诉的问题,动态的为类添加额外的功能。
 
先来看看装饰器的定义:动态的为一个对象增加额外的功能。就增加功能来说,装饰器模式相比生成子类更为灵活。
 
通用类图如下:
 
 
对上面的类图做个简单的介绍:
Component,一般是接口或者抽象类,定义了最简单的方法,装饰器类和被装饰类都要实现该接口。
 
ConcreteComponent,被装饰类,实现了Component。
 
Decorator,装饰器类,通过该类为ConcreteComponent动态添加额外的方法,实现了Component接口,并且该对象中持有一个Component的成员变量。
 
ConcreteDecoratorA,ConcreteDecoratorB,具体的装饰类,该类中的方法就是要为ConcreteComponent动态添加的方法。
 
继续使用上面的例子看看使用装饰器模式如何给Student类动态添加方法。
 
首先定义一个StudentSourcable的接口,里面有个study的方法,代码如下:
 
public interface StudentSourcable {
    public void study();
}
 
然后定义个Student类,实现了StudentSourcable 接口,这个类就是被装饰类,代码如下:
 
public class Student implements StudentSourcable{
    public void study(){
        System.out.println("我是一个学生,学习是我的天职。");
    }
}
 
接着定义一个装饰器类StudentDecorator,该类持有一个StudentSourcable的私有实例对象,实现了StudentSourcable接口,代码如下:
public class StudentDecorator implements StudentSourcable{
    private StudentSourcable source;
 
    public StudentDecorator(StudentSourcable source){
//        super(source);
        this.source = source;
    }
 
    public void study(){
        source.study();
    }
}
 
最后把上面例子中的FootballStudent和BasketballStudent两个类做下简单的修改,修改为继承StudentDecorator类,然后重写study方法,代码如下:
FootballStudent.java
public class FootballStudent extends StudentDecorator{
    public FootballStudent(StudentSourcable source){
        super(source);
    }
    public void playFootball(){
        System.out.println("我喜欢踢足球。");
    }
 
    public void study(){
        super.study();
        this.playFootball();
    }
}
 
BasketballStudent.java
public class BasketballStudent extends StudentDecorator{
    public BasketballStudent(StudentSourcable source){
        super(source);
    }
    public void playBasketball(){
        System.out.println("我喜欢打篮球");
    }
 
    public void study(){
        super.study();
        this.playBasketball();
    }
}
 
创建一个Client测试下,代码如下:
 
public class Client{
    public static void main(String args[]){
        StudentSourcable student = new Student();
        student = new FootballStudent(student);
        student = new BasketballStudent(student);
        student.study();
    }
}
 
执行的结果为:
我是一个学生,学习是我的天职。
我喜欢踢足球。
我喜欢打篮球
 
上面的例子是不是比继承来扩展一个类的功能来得简单,并且是的动态添加功能,所谓的动态添加功能,就是在Client类中(也是我们要实现某个功能的代码中)通过 student = new FootballStudent(student)代码为Student添加一个踢足球的功能。如果我们不想给Student添加踢足球的功能,只需注释掉这行代码即可。
 
装饰器模式的缺点就是会产生很多相似的类,出错时查找问题比较麻烦。
转载来源 http://blog.csdn.net/u011811966/article/details/52678029
posted @ 2018-02-24 09:36  人情世故zzz  阅读(110)  评论(0编辑  收藏  举报