外观类??为了代码的安全调用

来源:互联网 发布:叶公好龙知乎 编辑:程序博客网 时间:2024/05/21 07:00

看了《How Tomcat Works》一书中第二章节的部分代码中提到了“外观类”一词,看了文中代码实现原理与解释,说文中外观类是为了实现类中方法调用的安全性考虑。

其主要实现就是:

<span style="font-family:Microsoft YaHei;font-size:14px;">public void process(Request request, Response response) { Request,Response 类分别对象继承ServletRequest,ServletResponse类</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">.......代码省略</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">try {      servlet = (Servlet) myClass.newInstance();      servlet.service((<span style="background-color: rgb(255, 102, 102);">ServletRequest</span>) request, (<span style="background-color: rgb(255, 0, 0);">ServletResponse</span>) response); //该处将Request强制转换为          }</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">......</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">}</span>
图中红色部分将request 对象强制转换为其接口类,这样做的效果在我看来有点类似有子类继承中的向上转型,该对象中仅能调用ServletRequest接口自身的方法,对于Request后来增加的方法将无法调用。

但又有新的问题,尽管强制转换后的包外(不在同一个包中)获得的 (ServletRequest) request对象对于Request 对象中的新增方法无法调用,但其又可以通过向下转型为Request 的实例,使得获得(ServletRequest) request 的 ServletRequest 实例又可以调用Request中的一些 ”不想在此处被调用“的方法,这样就会出现了不安全调用的问题。

解决问题的方法可能有人会想到,不如直接将Request 中的新增方法都设置为私有方法,但在这里我们对于却限定了,这些方法在部分其他类又要能被调用。故这样是不行的。  由于是为了防止包外类中对 对象的方法调用,故其实可以就将不想被访问的方法设置为默认的访问修饰符,即包间不可见。

但是这里有一个更好的方法,使用“外观”类。

<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="background-color: rgb(255, 204, 204);">     RequestFacade requestFacade = new RequestFacade(request);    ResponseFacade responseFacade = new ResponseFacade(response);</span></span>
<span style="font-family:Microsoft YaHei;font-size:14px;"> try {      servlet = (Servlet) myClass.newInstance();      servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);          }</span>


RequestFacade 类:

<span style="font-family:Microsoft YaHei;font-size:14px;">public class RequestFacade implements ServletRequest {  private ServletRequest request = null;  public RequestFacade(Request request) {    this.request = request;  }</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">   .........接口实现类</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">}</span>
注意到RequestFacade 类的构造函数,它接受一个Request对象,但立即将其赋值给私有的 ServletRequest 对象引用。由于对象ServletRequest 对象本身是私有的,无法从类外部进行访问。相比于将Request对象向上转型为ServletRequest对象,并将其传给service()方法,这里会创建一个RequestFacade对象,再将其传递给service()方法。servlet程序猿仍然可以将servletRequest 实例向下转型为RequestFacade对象,但他们只能访问ServletRequest接口中提供的方法。现在request中自己新增加的方法就安全了。


1 0
原创粉丝点击