再谈装饰器模式

前言

去年作大实验初次接触了装饰器模式,当时也是懵懵懂懂过去了,没有太搞明白。最近学习的时候又接触了装饰器模式,同时又有了一些新的理解。app

举例

咱们会用到框架自带的已经封装好的方法,这节省了咱们写不少原生方法的时间,可是这些封装好的代码可能又不是十分符合咱们所须要的,咱们须要对此进行一些修改。就如同它的名字,咱们须要对封装好的代码进行一下“装饰”。
咱们本着对对修改关闭,对扩展开放的原则,对代码进行修改。在这里我举个例子。
原来有一家生产并在本地零售玻璃杯的厂家,有一天来了一个商人说要订购大量玻璃杯并运输到外地去卖,他但愿厂家能够吧生产的玻璃杯用泡沫板包装好以即可以运输。这是厂家特地开辟了一条生产线去给杯子包裹泡沫板,这时商家满意了。
商家想要买杯子,可是如今生产的杯子没有彻底获得他的满意,因而厂家在不改变原来生产线的状况下,添加了新的生产线,来知足客户需求。客户获得的仍是杯子,可是是被装饰过的杯子。这就是咱们的装饰器模式。框架

doem

仍是那教程中例子来讲明dom

class Request {
    String getHeader(String key) {
        // 获取header值的真实代码略
    }
}

class TokenFilterTest {
   
    /**在此传入auth-token的值*/
    @Test
    void doFilter() {
        String authToken = "654321";
        Request request = new Request();
        this.getAuthUser(request);
    }
    /** 在此获取auth-token的值 */
    void getAuthUser(Request request) {
        // 获取auth-token
        request.getHeader("auth-token");
        // 根据auth-token获取当前登陆用户
    }

}

假设框架已经封装好了Request类和类里的getHeader方法,咱们在TokenFilterTest类里须要调用getHeader方法,可是getHeader方法是框架为咱们封装好的,咱们不能改变他的代码,可是现有的方法又打不到咱们如今的需求,咱们就为他创建一个新的类,可是必定要继承咱们原来的类。ide

class RequestWrapper extends Request {
    Request request; 
    
    private RequestWrapper() { 
    }
    
    public RequestWrapper(Request request) { 
        this.request = request;
    }

    @Override
    String getHeader(String key) { 
        return this.request.getHeader(key); 
    }
}

咱们经过继承Request类是能够调用getHeader方法的,可是咱们的目的是在这个方法的基础上进行改造,函数

class RequestWrapper extends Request {
    ...
    @Override
    String getHeader(String key) {
        if ("auth-token".equals(key)) {
            // 在此返回新的auth-token值
            return "456789";
        }
        return this.request.getHeader(key);
    }
}

这样一个新的方法就写好了,咱们如今去调用这个方法学习

public class TokenFilterTest {

    @Test
    public void doFilter() {
        String authToken = new RandomString(6).nextString();
        System.out.println("authToken传入值为" + authToken);
        Request request = new Request();
        RequestWrapper requestWrapper = new RequestWrapper(request, authToken);
        this.getAuthUser(requestWrapper);
    }
    
    
    /** 在此获取auth-token的值 */
    void getAuthUser(Request request) {
        // 获取auth-token
        System.out.println("获取到的auth-token值为:" + request.getHeader("auth-token"));

        // 根据auth-token获取当前登陆用户
    }

}

咱们发现咱们在getAuthUser方法并无改变他传入的参数类型,可是咱们在调用他的时候已经由传入request变成requestWrapper,说明咱们并无改变他的类型,可是咱们确实是用的RequestWrapper构造函数获取到的。
image.png
原来咱们三个方法的关系是这样的.
image.png
如今咱们对他装饰一下。咱们发现咱们并无改变getAuthUser。也不用改变getHeader,由于咱们的RequestWrapper类继承了Request类。this

总结

对于装饰器模式已经有不少次接触了,每次接触都会带来新的理解,也会带来提升。spa

相关文章
相关标签/搜索