外观模式(Facade Pattern)

《深入剖析Tomcat》(How Tomcat Works),第二章。

创建 RequestResponse 分别实现 ServletRequestServletResponse,然后将这两个对象传给实现了 Servlet 接口的 PrimitiveServlet 类的service方法。

下面代码中的 request 和 response 除了实现 ServletRequestServletResponse 接口中的方法,还分别自定义了 getUri 和 sendStaticResource 方法,如果将他们向上转为 ServletRequestServletResponse,那么在 PrimitiveServlet 中如果被向下转为 Request 和 Response,则可以调用 getUri 和 sendStaticResource 方法,这被认为是不安全的。

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

如果将 getUri 和 sendStaticResource 声明为私有,则可以防止在 servlet 中被调用,但是在其他可能被安全地调用的地方也不能用了,不可以。如果给方法以默认访问权限,则只能在同一个包中访问,这个被认为是可以的,但是不最好,最优雅的方式是通过 facade 类。

具体做法是定义 RequestFacade 和 ResponseFacade 两个类,分别实现 ServletRequest 和 ServletResponse,同时定义私有成员变量 Request 和 Response,并且方法的实现调用 Request 和 Response 的实现。然后,将 RequestFacade 和 ResponseFacade 上转为 ServletRequest 和 ServletResponse 传给 servlet 的 service 方法,这样即使在 servlet 中被下转为 RequestFacade 和 ResponseFacade,也不能访问私有成员变量对象中的方法。既用了 Request 和 Response 的实现,又能防止其中自定义的方法被不合理的访问。

类图如下:

代码:

    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]

  • 以下来自维基百科

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.(一个复杂的,难以理解的系统)

大话设计模式中基金与股票的例子挺好的,这幅图也很好:

下面是维基百科上的示例代码,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, 第二章

你可能感兴趣的:(java,设计模式,servlet,tomcat)