4

前言

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

举例

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

doem

还是那教程中例子来说明


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方法是框架为我们封装好的,我们不能改变他的代码,但是现有的方法又打不到我们现在的需求,我们就为他建立一个新的类,但是一定要继承我们原来的类。

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类。

总结

对于装饰器模式已经有很多次接触了,每次接触都会带来新的理解,也会带来提高。


小强Zzz
1.2k 声望32 粉丝