当前项目中的程序不使用缺省适配器模式,分析程序存在的缺点:
假设接口CommonIn有7个方法,当前程序中实现类A,B,C只需要使用CommonIn接口中的m1,m2,m3方法,让这些类直接实现这个接口,需要实现更多的方法,代码丑陋。
我们直接实现Servlet接口,程序员几乎只用操作一个service方法,其他的“多余”了
当前项目中的程序使用缺省适配器模式,代码优雅
那写个类来实现这个接口会用到的部分方法,我们再来继承这个类就可以了啊?
这个类就是抽象类,因为普通类实现接口,必须覆写全部接口方法,而抽象类可以不用,它可以选择留出关键方法让子类去覆写而子类不用管其他的方法,还可以追加普通方法提供给子类使用。
这个抽象类就是适配器。
设计模式的分类:
- 创建型: 解决对象的创建问题
- 行为型: 该模式与方法、行为、算法有关的设计模式
- 结构型: 更多类,更多的对象组合成更大的结构解决某个特定的问题
你听说过哪些设计模式?
-
Gof95(1995年, 四人组提出的23种设计模式)
- 单例模式
- 工厂模式
- 适器模式
- 迭代模式[集合]
- 策略模式[集合]
- 装饰器模式[I0流]
- …
-
JavaEE设计模式
- …
Servlet的适配器模式
定义一个抽象类GenericServlet来充当适配器
package com.gkd.javeee;
import ...
public abstract class GenericServlet implements Servlet {
private ServletConfig config;
@Override
public void destroy() {
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
@Override
public abstract void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException;
//------------------扩展普通方法增强子类------------------
public ServletContext getServletContext( ) {
return this.getServletConfig().getServletContext();
}
}
真正的业务servlet来继承这个抽象类:
package com.gkd.javeee;
import ...
public class MyServlet extends GenericServlet {
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("hhhh");
}
}
现在有一个问题:
- Servlet子类想要在初始化时执行一些操作怎么办?比如记录日志。
正常来说,子类覆写抽象类GenericServlet中的普通方法init()方法即可,但现在init方法希望不被人覆写,加上了关键字final
public abstract class GenericServlet implements Servlet {
...
public final void init(ServletConfig config) throws ServletException {
this.config = config;
}
...
}
现在我们不能覆写inti()方法了,但是我们能覆写普通方法啊,只要能让这个普通方法在初始化时执行,不一样达到目的在初始化时执行了一些操作吗
可以这么做:
public abstract class GenericServlet implements Servlet {
...
public final void init(ServletConfig config) throws ServletException {
this.config = config;
this.hhh();
}
public void hhh() {}
...
}
这样我们在子类只要覆写hhh()方法就可以了,不过hhh()命名最好命为init(),以达到望文知义的目的。
上面的适配器是我们自己写的,但是sun公司其实已经帮我们写了一个javax.Servlet.GenericServlet
//sun公司提供的适配器中的init()方法
public final void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
Sun公司提供的适配器GenericServlet的init()方法没有加关键字final,也就是子类可以直接覆写init()方法。
如果子类覆写了init()方法,那适配器init()方法中的this.config = config;
语句就不会执行,除非子类覆写的时候第一句写上super.init(config)
(super关键字代表父类,在这里有点像把父类方法的代码整合到子类要重写的方法里。这是JavaSE关键字super的知识了)
sun公司考虑了这一点,所以为了方便程序员在子类覆写init()方法,就用了this.hhh()
的操作,让程序员覆写的其实是个普通方法,不用写super.init(config)
,父类的方法中的代码一样可以被执行到。
真是个好想法啊!