zoukankan      html  css  js  c++  java
  • 设计模式之装饰器模式

    装饰器模式,顾名思义就是在一个原有的类的上增加额外的功能,前提是不能修改类的代码。其实为一个类增加功能,可以用继承来实现,但是这样会使得类的数量层爆炸式增长,每增加一个功能,都会通过继承生成一个新类。我们使用代码来验证上面的结论:
     
    类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
  • 相关阅读:
    spring无法接收上传文件
    springcloud feign增加熔断器Hystrix
    mybatis调用存储过程(@Select方式)
    spring在注解标注的方法上加切面
    java注解Annotation
    java包装类
    JZ-C-43
    JZ-C-42-Plus
    JZ-C-42
    JZ-C-41-Plus
  • 原文地址:https://www.cnblogs.com/liukunjava/p/8464136.html
Copyright © 2011-2022 走看看