设计模式之装饰器模式
装饰器模式,顾名思义就是在一个原有的类的上增加额外的功能,前提是不能修改类的代码。其实为一个类增加功能,可以用继承来实现,但是这样会使得类的数量层爆炸式增长,每增加一个功能,都会通过继承生成一个新类。我们使用代码来验证上面的结论:
类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