外觀模式(Facade Pattern)

《深刻剖析Tomcat》(How Tomcat Works),第二章。設計模式

建立 RequestResponse 分別實現 ServletRequestServletResponse,而後將這兩個對象傳給實現了 Servlet 接口的 PrimitiveServlet 類的service方法。安全

下面代碼中的 request 和 response 除了實現 ServletRequestServletResponse 接口中的方法,還分別自定義了 getUri 和 sendStaticResource 方法,若是將他們向上轉爲 ServletRequestServletResponse,那麼在 PrimitiveServlet 中若是被向下轉爲 Request 和 Response,則能夠調用 getUri 和 sendStaticResource 方法,這被認爲是不安全的。ui

Request request = ...
    Response response = ...
    servlet = (Servlet) myClass.newInstance();
    servlet.service((ServletRequest) request, (ServletResponse) response);

若是將 getUri 和 sendStaticResource 聲明爲私有,則能夠防止在 servlet 中被調用,可是在其餘可能被安全地調用的地方也不能用了,不能夠。若是給方法以默認訪問權限,則只能在同一個包中訪問,這個被認爲是能夠的,可是不最好,最優雅的方式是經過 facade 類。this

具體作法是定義 RequestFacade 和 ResponseFacade 兩個類,分別實現 ServletRequest 和 ServletResponse,同時定義私有成員變量 Request 和 Response,而且方法的實現調用 Request 和 Response 的實現。而後,將 RequestFacade 和 ResponseFacade 上轉爲 ServletRequest 和 ServletResponse 傳給 servlet 的 service 方法,這樣即便在 servlet 中被下轉爲 RequestFacade 和 ResponseFacade,也不能訪問私有成員變量對象中的方法。既用了 Request 和 Response 的實現,又能防止其中自定義的方法被不合理的訪問。spa

類圖以下:設計

clipboard.png

代碼:code

public class RequestFacade implements ServletRequest {
    
        private ServleLRequest request = null;
        
        public RequestFacade(Request request) {
            this.request = request;
        }
        
        /* implementation of the ServletRequest*/
        public Object getAttribute(String attribute) {
            return request.getAttribute(attribute);
        }
        
        ...
    }
    
    // ResponseFacade相似
    
    RequestFacade requestFacade = new RequestFacade(request);
    ResponseFacade responseFacade = new ResponseFacade(response);
    try {
        servlet = (Servlet) myClass.newInstance();
        servlet.service((ServletRequest) requestFacade,(ServletResponse)responseFacade);
    }

下面是Facade模式的一些內容,與上面的用法不太同樣。對象

  • 定義接口

外觀模式(Facade),爲子系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。[DP]ip

  • 如下來自維基百科

The facade pattern is typically used when:(外觀模式的典型用法)

  • a simple interface is required to access a complex system; (須要簡單的接口去訪問複雜的系統)

  • the abstractions and implementations of a subsystem are tightly coupled;(子系統的抽象和實現是緊密耦合的)

  • need an entry point to each level of layered software; or(須要一個入口去訪問分層軟件的每一層)

  • a system is very complex or difficult to understand.(一個複雜的,難以理解的系統)

clipboard.png

大話設計模式中基金與股票的例子挺好的,這幅圖也很好:
clipboard.png

下面是維基百科上的示例代碼,Java版:

/* Complex parts */

class CPU {
    public void freeze() { ... }
    public void jump(long position) { ... }
    public void execute() { ... }
}

class Memory {
    public void load(long position, byte[] data) { ... }
}

class HardDrive {
    public byte[] read(long lba, int size) { ... }
}

/* Facade */

class ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hd;

    public ComputerFacade() {
        this.processor = new CPU();
        this.ram = new Memory();
        this.hd = new HardDrive();
    }

    public void start() {
        processor.freeze();
        ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
        processor.jump(BOOT_ADDRESS);
        processor.execute();
    }
}

/* Client */

class You {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

參考:

  1. 維基百科:https://en.wikipedia.org/wiki...

  2. 大話設計模式第12章 外觀模式

  3. How Tomcat Works, 第二章

相關文章
相關標籤/搜索