模板方法模式(Template Method)
模板方法模式是一种行为设计模式,它在一个超类中定义一个算法骨架,并将某些步骤推迟到子类中实现。
模板方法可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
优点:
缺点:
final
修饰模板方法防止子类重写。回调(Callback)也能起到跟模板模式相同的作用。 同步回调看起来更像模板模式,异步回调看起来更像观察者模式。
模板方法类
public abstract class Computer {
private String mainboard = "自带主板";
protected String cpu;
protected String gpu;
protected String ram;
protected String rom;
// final 防止子类重写
public final void buildComputer() {
installCpu();
installGpu();
installRam();
installRom();
}
// 抽象方法,给子类实现
protected abstract void installCpu();
// 抽象方法,给子类实现
protected abstract void installGpu();
// 默认实现
protected void installRam() {
this.ram = "8G";
}
// 默认实现
protected void installRom() {
this.rom = "512G固态";
}
public String show() {
return "Computer{" +
"mainboard='" + mainboard + '\'' +
", cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", ram='" + ram + '\'' +
", rom='" + rom + '\'' +
'}';
}
}
实现类
public class OfficeComputer extends Computer {
@Override
protected void installCpu() {
this.cpu = "intel i5 ";
}
@Override
protected void installGpu() {
this.gpu = "intel i5 集成显卡";
}
}
public class GamingComputer extends Computer {
@Override
protected void installCpu() {
this.cpu = "amd 5900x";
}
@Override
protected void installGpu() {
this.gpu = "nvidia 3090 super";
}
@Override
protected void installRam() {
this.ram = "16G";
}
@Override
protected void installRom() {
this.rom = "1T 固态";
}
}
public class ProgrammingComputer extends Computer {
@Override
protected void installCpu() {
this.cpu = "amd 5900x";
}
@Override
protected void installGpu() {
this.gpu = "nvidia 2070 super";
}
@Override
protected void installRam() {
this.ram = "64G";
}
@Override
protected void installRom() {
this.rom = "2T 固态";
}
}
测试代码
public class TemplateTest {
@Test
public void test() {
Computer officeComputer = new OfficeComputer();
Computer gamingComputer = new GamingComputer();
Computer programmingComputer = new ProgrammingComputer();
officeComputer.buildComputer();
System.out.println(officeComputer.show());
gamingComputer.buildComputer();
System.out.println(gamingComputer.show());
programmingComputer.buildComputer();
System.out.println(programmingComputer.show());
}
}
public abstract class InputStream implements Closeable {
//...省略其他代码...
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte) c;
int i = 1;
try {
for (; i < len; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte) c;
}
} catch (IOException ee) {
}
return i;
}
public abstract int read() throws IOException;
}
public class ByteArrayInputStream extends InputStream {
//...省略其他代码...
@Override
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
}
自己的实现
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello World.");
}
}
模板类
public abstract class HttpServlet extends GenericServlet implements Serializable {
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String HEADER_LASTMOD = "Last-Modified";
private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");
/**
* 将请求及响应 转换成 HttpServletRequest 及 HttpServletResponse,
* 再调用 service() 的重载方法
*/
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
/**
* 对 HTTP 协议各种类型的请求分别进行处理 (模板方法)
*/
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
if (method.equals("GET")) {
long lastModified = getLastModified(req);
if (lastModified == -1L) {
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < (lastModified / 1000L) * 1000L) {
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals("POST"))
doPost(req, resp);
else if (method.equals("PUT"))
doPut(req, resp);
else if (method.equals("DELETE"))
doDelete(req, resp);
else if (method.equals("OPTIONS"))
doOptions(req, resp);
else if (method.equals("TRACE")) {
doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object errArgs[] = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1"))
resp.sendError(405, msg);
else
resp.sendError(400, msg);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1"))
resp.sendError(405, msg);
else
resp.sendError(400, msg);
}
protected long getLastModified(HttpServletRequest req) {
return -1L;
}
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
NoBodyResponse response = new NoBodyResponse(resp);
doGet(req, response);
response.setContentLength();
}
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ...
}
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ...
}
private Method[] getAllDeclaredMethods(Class c) {
// ...
}
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Method methods[] = getAllDeclaredMethods(getClass());
// ...
}
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ...
}
private void maybeSetLastModified(HttpServletResponse resp, long lastModified) {
// ...
}
}
以上代码与文章会同步到 github 仓库:
/chenbihao/Design-Patterns