模板设计模式

本文深入探讨了模板设计模式的应用,通过实例展示了如何在不同文化背景下就餐流程的共性和个性,解释了抽象模板和具体模板的角色职责,以及模板方法在代码骨架定义中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模板设计模式:

在生活中比如出去吃饭,①先下订单–》②吃饭–》③吃水果–》④结账,在整个过程中流程是不变的,但是第二个步骤可能因为人的不同国家或者名族吃饭方式不同(所以饭店不可能规定出吃饭的方式,客户自己选择吃饭的方式),第三个步骤可以客户可以自己选择要吃的水果,如果不选择那么商家就默认给你香蕉,第四个步骤由于商家没跟上互联网的时代,所以只能支持现金支付(这时候商家要求客户必须使用现金支付的)

 package com.sxt;
class Chinese{
	/**
	 * 这是必须的
	 */
	 public  void   placeOrder() {
		 System.out.println("下订单");
	 }
	 /**
	  * 商家不能规定客户的吃饭方式,必须客户自己选择
	  */
	 public  void  haveMeal() {
		 System.out.println("使用筷子吃饭");
	 }
	 /**
	  *  客户也可以自己选择要吃什么水果,如果不选也可以,但是会给默认的水果
	  */
	 public  void  doHaveFruit() { //这种方法在模板设计 模式中叫做钩子方法
		 System.out.println("吃苹果"); 
	 }
	 /**
	  *  商家强制要求必须使用现金
	  */
	 public  void  acount() {
		 System.out.println("只能现金结账");
	 }
}
//西方人
class European {
	/**
	 * 这是必须的
	 */
	 public  void   placeOrder() {
		 System.out.println("下订单");
	 }
	 /**
	  * 商家不能规定客户的吃饭方式,必须客户自己选择
	  */
	 public  void  haveMeal() {
		 System.out.println("使用刀叉吃饭");
	 }
	 /**
	  *  客户也可以自己选择要吃什么水果,如果不选也可以,但是会给默认的水果
	  */
	 public  void  doHaveFruit() { //这种方法在模板设计 模式中叫做钩子方法
		 System.out.println("吃苹果"); 
	 }
	 /**
	  *  商家强制要求必须使用现金
	  */
	 public  void  acount() {
		 System.out.println("只能现金结账");
	 }
}
//非洲人
class  Africa{
	/**
	 * 这是必须的
	 */
	 public  void   placeOrder() {
		 System.out.println("下订单");
	 }
	 /**
	  * 商家不能规定客户的吃饭方式,必须客户自己选择
	  */
	 public  void  haveMeal() {
		 System.out.println("使用手抓");
	 }
	 /**
	  *  客户也可以自己选择要吃什么水果,如果不选也可以,但是会给默认的水果
	  */
	 public  void  doHaveFruit() { //这种方法在模板设计 模式中叫做钩子方法
		 System.out.println("吃橘子"); 
	 }
	 /**
	  *  商家强制要求必须使用现金
	  */
	 public  void  acount() {
		 System.out.println("只能现金结账");
	 }
}
public class Test{
   public static void main(String[] args) {
	   //中国人去吃饭
	   Chinese  chinese=new Chinese();
	   chinese.placeOrder();
	   chinese.haveMeal();
	   chinese.doHaveFruit();
	   chinese.acount();
	   System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
	   //西方人人去吃饭
	   European  european=new European();
	   european.placeOrder();
	   european.haveMeal();
	   european.doHaveFruit();
	   european.acount();
	   System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
	   //非洲人去吃饭
	   Africa  africa=new Africa();
	   africa.placeOrder();
	   africa.haveMeal();
	   africa.doHaveFruit();
	   africa.acount();
	   
   }
}

在这里插入图片描述
以上的三个类在使用的时候调用形式都是重复的, 此时为了解决这样的问题提出了模板设计模式, 定义出一个抽象父类,在该父类中组织子类方法的调用,在父类中定义出一个方法来实现子类方法调用的组织,这个方法叫做模板方法,该类叫做模板类,在模板类中一般会有如下特征的方法:
•模板方法:组织子类方法的调用,定义出了一个骨架
=•抽象方法:要求子类覆写的方法(比如说吃饭的方法就是要求子类自己选择方式)=
•final修饰的方法:该方法不让被子类覆写(结账的时候只能是现金支付)
•钩子方法:在父类中默认实现了,子类可以选择性的覆写,这样的方法的名称一般以do开头(吃水果的时候可以自己选择,也可以不选择,因为商家会按照默认方式给出水果)。

package com.sxt;

public class TestDemo04 {
	public static void main(String[] args) {
		Chinese c = new Chinese();
		c.enjoy();
		System.out.println("====================================");
		Europe e = new Europe();
		e.enjoy();
		System.out.println("====================================");
		Africa a = new Africa();
		a.enjoy();
	}
}
abstract class TempletPattern {
	public final void placeOrder() {
		System.out.println("下订单");
	}
	public abstract void haveMeal();
	
	public void doHaveFruit() {	//钩子方法,子类可以选择复写
		System.out.println("吃苹果");
	}
	
	public final void acount() {
		System.out.println("只支持现金支付");
	} 
	public void enjoy() {
		this.placeOrder();
		this.haveMeal();
		this.doHaveFruit();
		this.acount();
	}
}
class Chinese extends TempletPattern {
	@Override
	public void haveMeal() {
		System.out.println("使用筷子吃饭");
	}
}
class Europe extends TempletPattern {
	@Override
	public void haveMeal() {
		System.out.println("使用刀叉吃饭");
	}
	@Override
	public void doHaveFruit() {
		System.out.println("吃草莓");
	}
}
class Africa extends TempletPattern {
	@Override
	public void haveMeal() {
		System.out.println("手抓");
	}
	@Override
	public void doHaveFruit() {
		System.out.println("吃香蕉");
	}
}

在这里插入图片描述
此时就是使用模板设计模式定义出了代码的骨架,去出累赘的调用代码。
总结:
这里涉及到两个角色:
抽象模板(Abstract Template)角色有如下责任:
  ■ 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作
  ■ 定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。
具体模板(Concrete Template)角色又如下责任:
  ■ 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。

模板方法的使用场景(了解)

使用过Servlet的人都清楚,除了要在web.xml做相应的配置外,还需继承一个叫HttpServlet的抽象类。HttpServlet类提供了一个service()方法,这个方法调用七个do方法中的一个或几个,完成对客户端调用的响应。这些do方法需要由HttpServlet的具体子类提供,因此这是典型的模板方法模式。下面是service()方法的源代码:

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
            
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
            
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
            
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

实际上在发送请求到servlet的时候是先访问到模板类(HttpServlet)中的service方法。再有这个模板方法中判断调用具体的doXXXX方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值