一篇博客读懂设计模式之---模板方法模式
設(shè)計(jì)模式之模板方法模式:
定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
簡(jiǎn)而言之就是:父類定義了骨架(調(diào)用哪些方法及其順序),某些特定的方法由具體的子類來(lái)實(shí)現(xiàn)。
所以呢?在父類模板方法中是有兩類方法的:
1). 抽象方法:父類是抽象方法,子類必須實(shí)現(xiàn)的,如下面的startGame,endGame方法;
2). 鉤子方法:父類中是一個(gè)空方法,子類繼承的時(shí)候默認(rèn)也是空的,這個(gè)方法有什么用呢?子類可以通過(guò)這個(gè)方法來(lái)自定義自己的其他一些步驟和過(guò)程,從而達(dá)到控制父類的目的。
我們將創(chuàng)建一個(gè)定義操作的 Game 抽象類,其中,模板方法設(shè)置為 final,這樣它就不會(huì)被重寫(xiě)。BasketballGame和 FootballGame 是擴(kuò)展了 Game 的實(shí)體類,它們重寫(xiě)了抽象類的方法。
1. 創(chuàng)建抽象類Game:
public abstract class Game {abstract void startGame();abstract void endGame();abstract void init();final void play(){init();startGame();endGame();} }2. 創(chuàng)建擴(kuò)展了上述類的實(shí)體類:
public class FootballGame extends Game {@Overridevoid startGame() {System.out.println("start football");}@Overridevoid endGame() {System.out.println("end football");}@Overridevoid init() {System.out.println("init football");} } public class BasketballGame extends Game {@Overridevoid startGame() {System.out.println("start basketball");}@Overridevoid endGame() {System.out.println("end basketball");}@Overridevoid init() {System.out.println("init basketball");} }3. 使用測(cè)試類測(cè)試:
public class TemplMain {public static void main(String[] args) {Game game = new FootballGame();//這樣如果你想要改變其他球類,只需要換成下面這種形式,其他不用改變//Game game = new BasketballGame();game.play();} }再升級(jí)一下,舉另一個(gè)例子:
接口描述的是一種共性,一種動(dòng)作action;
抽象類描述的是一個(gè)模板,一個(gè)特定的過(guò)程;
而子類則是可以根據(jù)自己的需要定制自己的過(guò)程。
不過(guò),這樣做的好處又是什么呢?
其實(shí)我們?cè)谝恍┛蚣?#xff0c;如spring,mybatis等都可以看到模板方法模式的影子,下面簡(jiǎn)單舉一下例子:
像mybatis的Executor接口:
你就可以很明顯的看到這種模式:
spring中的模板方法模式:
spring模板方法我來(lái)摘抄一些重點(diǎn)給大家看看:
下面的代碼展示了Spring IOC容器初始化時(shí)運(yùn)用到的模板方法模式。(截取部分關(guān)鍵代碼)
1、首先定義一個(gè)接口ConfigurableApplicationContext,聲明模板方法refresh
2、抽象類AbstractApplicationContext實(shí)現(xiàn)了接口,主要實(shí)現(xiàn)了模板方法refresh(這個(gè)方法很重要,是各種IOC容器初始化的入口)的邏輯:
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext, DisposableBean {/**模板方法的具體實(shí)現(xiàn)*/public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();//注意這個(gè)方法是,里面調(diào)用了兩個(gè)抽象方法refreshBeanFactory、getBeanFactory// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {//注意這個(gè)方法是鉤子方法,點(diǎn)進(jìn)去父類看可以發(fā)現(xiàn)是空的// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();//注意這個(gè)方法是鉤子方法// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}}} }這里最主要有一個(gè)抽象方法obtainFreshBeanFactory、兩個(gè)鉤子方法postProcessBeanFactory和onRefresh,看看他們?cè)陬愔械亩x
看看獲取Spring容器的抽象方法:
3、具體實(shí)現(xiàn)的子類,實(shí)現(xiàn)了抽象方法getBeanFactory的子類有:
AbstractRefreshableApplicationContext:
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {@Overridepublic final ConfigurableListableBeanFactory getBeanFactory() {synchronized (this.beanFactoryMonitor) {if (this.beanFactory == null) {throw new IllegalStateException("BeanFactory not initialized or already closed - " +"call 'refresh' before accessing beans via the ApplicationContext");}//這里的this.beanFactory在另一個(gè)抽象方法refreshBeanFactory的設(shè)置的return this.beanFactory;}} }GenericApplicationContext:
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {@Overridepublic final ConfigurableListableBeanFactory getBeanFactory() {//同樣這里的this.beanFactory在另一個(gè)抽象方法中設(shè)置 return this.beanFactory;} }大家有空可以自己進(jìn)去看看里面的源碼!里面真是高深莫測(cè)!
總結(jié)
以上是生活随笔為你收集整理的一篇博客读懂设计模式之---模板方法模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java 集合Collection常见知
- 下一篇: asp.net ajax控件工具集 Au