《深入剖析Tomcat》(How Tomcat Works),第二章。
创建Request和Response分别实现ServletRequest和ServletResponse,然后将这两个对象传给实现了Servlet接口的PrimitiveServlet类的service方法。
下面代码中的request和response除了实现ServletRequest和ServletResponse接口中的方法,还分别自定义了getUri()和sendStaticResource()方法,如果将他们向上转为ServletRequest和ServletResponse,那么在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();
}
}
参考:
大话设计模式第12章 外观模式
How Tomcat Works, 第二章