接口向下转型,子类方法安全问题

  举个栗子,HttpServlet有这么一个方法 service(HttpServletRequest req, HttpServletResponse resp),两个参数类型都是接口;HttpServletRequest是Servlet提供的一个接口,它会有很多实现类,这些类会实现接口方法,也可能会新增自己的方法。service()在处理请求时使用到req,req可以调用接口方法;在开发人员知道req具体的实现类的情况下,祂们可以将req向下转型成实现类,从而调用实现类的特有方法,这样的特有方法并不是每个实现类都有的。

  如下方代码,MyRequest则是HttpServletRequest的实现类。下方代码调用service()传入MyRequest实例,该实例会自动向上转型为HttpServletRequest类型。service()中调用MyRequest的getPrivateInfo()。这样编码将导致service()方法与调用方耦合,在改变参数实现类的同时需要改变service()的实现逻辑。所以我们应该杜绝这种向下转型的编码方式,但是仅仅靠编码规范怕是约束不了祂们(滑稽)。我们需要一种方法,禁止调用子类特有方法。

//service()调用
MyRequest myRequest = new MyRequest();
servlet.service(myRequest, myResponse);
public class MyRequest implements HttpServletRequest {
    MyRequest(){
        super();
    };

    public String getPrivateInfo() {
        return "";//私密信息
    }
    
    //以下为接口方法实现
    @Override
    public String getAuthType() {
        return null;
    }
    @Override
    public Cookie[] getCookies() {
        return new Cookie[0];
    }
    ...
}
service(HttpServletRequest req, HttpServletResponse resp) {
  MyRequest myRequest = (MyRequest)req;
  myRequest.getPrivateInfo(); }

 

  问题:如何禁止子类特有方法的调用

  改变特有方法的访问范围,protected或者private?特有方法有可能会在类外,甚至是包外调用,所以不行。(这里说的调用是类实例直接调用,不是什么说的向下转型再调用的情况)

  方法:借助外观类。代码如下,这时service()调用传入的是RequestFacade实例,通过该实例可以间接调用MyRequest实现的接口方法;而特有方法外观类没有,即使向下转型成RequestFacade也无法调用;RequestFacade类内的request属性又是私有的,无法通过request以原来的手段达到目的。这般如此,总算是遏制了那些歪门邪道,功德无量。

//service()调用
MyRequest myRequest = new MyRequest();
servlet.service(new RequestFacade(myRequest), new ResponseFacade(myResponse));
public class RequestFacade implements HttpServletRequest {

    private HttpServletRequest request;

    RequestFacade(HttpServletRequest request) {
        this.request = request;
    }
   //接口方法的实现直接调用构造方法传过来实例的方法
    @Override
    public String getAuthType() {
        return this.request.getAuthType();
    }
    @Override
    public Cookie[] getCookies() {
        return this.request.getCookies();
    }
  ... }

 

posted @ 2020-11-16 13:59  士三刀  阅读(195)  评论(0编辑  收藏  举报