一激涤、前言
說起來設(shè)計(jì)模式,大家應(yīng)該都耳熟能詳判呕,設(shè)計(jì)模式代表了軟件設(shè)計(jì)的最佳實(shí)踐倦踢,是經(jīng)過不斷總結(jié)提煉出來的代碼設(shè)計(jì)經(jīng)驗(yàn)的分類總結(jié),這些模式或者可以簡化代碼侠草,或者可以是代碼邏輯開起來清晰辱挥,或者對功能擴(kuò)展很方便…。
設(shè)計(jì)模式按照使用場景可以分為三大類:創(chuàng)建型模式(Creational Patterns)边涕、結(jié)構(gòu)型模式(Structural Patterns)晤碘、行為型模式(Behavioral Patterns)。
創(chuàng)建型模式(Creational Patterns)
對對象的實(shí)例化過程進(jìn)行抽象功蜓,這使得一個(gè)系統(tǒng)可以不用關(guān)心這些對象是如何創(chuàng)建园爷,組合,呈現(xiàn)的式撼,對于類創(chuàng)建模式來說通過使用繼承改變實(shí)例化的類童社,對于對象創(chuàng)建模式來說通過使用代理來實(shí)例化所需要的對象。
結(jié)構(gòu)型模式(Structural Patterns)
通過對多個(gè)類和對象進(jìn)行組合得到復(fù)雜結(jié)構(gòu)的類著隆,一般使用繼承繼承或者成員變量引用形式來實(shí)現(xiàn)扰楼。
行為型模式(Behavioral Patterns)
行為模式不僅表達(dá)了對象和類呀癣,還表達(dá)了他們之間的交互,涉及到了對象和算法的分配弦赖。
下面就帶大家看下開源框架框架中是如何應(yīng)用這些經(jīng)典設(shè)計(jì)模式的项栏。
二、責(zé)任鏈設(shè)計(jì)模式(Chain of Responsibility Pattern)
2.1 介紹
責(zé)任鏈模式是把多個(gè)對象串聯(lián)起來形成一個(gè)鏈狀結(jié)構(gòu)蹬竖,讓每個(gè)對象都有機(jī)會(huì)對事件發(fā)送者的請求進(jìn)行處理沼沈。責(zé)任鏈模式是設(shè)計(jì)模式中的行為模式,設(shè)計(jì)意圖是為了使事件發(fā)送者和事件接受者之間解耦币厕。通常責(zé)任鏈鏈中的每個(gè)對象都有下一個(gè)對象的引入(例如tomcat 里面StandardPipeline用來管理valve)庆冕,或者有個(gè)同一個(gè)鏈管理工廠里面使用數(shù)組存放了所有的對象(例如tomcat里面ApplicationFilterChain用來關(guān)系filter)。
2.2 Tomcat中Valve鏈
Tomcat中StandardEngine,StandardHost,StandardContext里面都有自己StandardPipeline,下面以StandardEngine里面StandardPipeline為例講解
image.png
從上面類圖可知道每個(gè)Valve都要繼承ValveBase類央渣,該類里面有一個(gè)Valve的引用入录,實(shí)際是鏈中下一個(gè)節(jié)點(diǎn)對象,Valve就是通過每個(gè)Valve里面的next串聯(lián)為鏈的。
每個(gè)valve的invoke方法里面調(diào)用next.invoke激活鏈中下一個(gè)節(jié)點(diǎn),并且StandardEngine,StandardHost,StandardContext都有一個(gè)basic valve這個(gè)valve在鏈的末尾用來激活子容器的valve鏈镶殷。
2.3 Tomcat中Filter鏈
Tomcat中Filter鏈?zhǔn)鞘褂肁pplicationFilterChain來管理的,具體結(jié)構(gòu)如下圖:
可知Filter鏈不是像Valve一樣在內(nèi)部維護(hù)下個(gè)節(jié)點(diǎn)的引用恋拷,而是在ApplicationFilterChain中搞了個(gè)數(shù)組存放所有的Filter准给,并通過n統(tǒng)計(jì)Filter總個(gè)數(shù),pos是當(dāng)前filter的下標(biāo)描滔。
ApplicationFilterChain的doFilter代碼如下:
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { ... internalDoFilter(request,response); ... }private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one if (pos < n) { //獲取filter鏈中下標(biāo)為pos的filter ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = null; try { filter = filterConfig.getFilter(); support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response); if (request.isAsyncSupported() && "false".equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } ... //調(diào)用自定義filter的dofilter方法 filter.doFilter(request, response, this); support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response); } .... } .....}
注:這兩種方式的區(qū)別是啥,就是說那些場景下使用2.2棒妨,什么情況下使用2.3這個(gè)目前還沒有搞清楚有
知道的麻煩在本帖留言幫我解惑下^^
2.4 使用場景
當(dāng)一個(gè)請求需要
根據(jù)請求參數(shù)的不同由不同對象來處理時(shí)候。
當(dāng)一個(gè)請求需要固定對象順序處理含长,并且可擴(kuò)展性的在固定順序里面插入新的對象進(jìn)行處理時(shí)候券腔。
三、工廠模式(Factory Pattern)
3.1 介紹
工廠模式是創(chuàng)建型模式拘泞,他封裝了對象的創(chuàng)建過程纷纫,調(diào)用者使用具體的工廠方法根據(jù)參數(shù)就可以獲取對應(yīng)的對象。
3.2 Spring框架中BeanFactory
如圖BeanFactory接口提供了getBean方法陪腌,在AbstractBeanFactory中實(shí)現(xiàn)了該方法辱魁,經(jīng)過層層繼承,實(shí)現(xiàn)诗鸭,最后DefaultListableBeanFactory實(shí)現(xiàn)了BeanDefinitionRegistry接口用來保存bean定義染簇,繼承了AbstractAutowireCapableBeanFactory用來支撐autowired。
一個(gè)例子
@Testpublic void testBeanFactoy() throws NamingException, SQLException, ParseException, IOException { //創(chuàng)建Bean工廠 DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); //給bean工廠添加bean定義,解析xml里面的bean放入bean工廠 loadBeanDefinitions(bf); //根據(jù)名字從bean工廠獲取bean Hello hello = (Hello) bf.getBean("hello"); hello.sayHello(); Hello2 hello2 = (Hello2) bf.getBean("hello2"); hello2.sayHello();}protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); String[] configLocations = new String[] { "beans2.xml" }; if (configLocations != null) { beanDefinitionReader.loadBeanDefinitions(configLocations); }}
3.3 使用場景
不同條件下創(chuàng)建不同實(shí)例强岸,用于統(tǒng)一管理bean
不同條件下調(diào)用不同工廠方法獲取不同場景下的bean
總結(jié)
設(shè)計(jì)模式中每一個(gè)模式都描述了在我們工作中不斷重復(fù)發(fā)生的問題锻弓,以及問題的解決方案,所以真正掌握設(shè)計(jì)模式可以避免我們做不必要的重復(fù)勞動(dòng)蝌箍。如果你在學(xué)習(xí)Java的過程中或者在工作中遇到什么問題都可以來群里提問弥咪,阿里Java高級大牛直播講解知識點(diǎn)过蹂,分享知識,多年工作經(jīng)驗(yàn)的梳理和總結(jié)聚至,帶著大家全面酷勺、科學(xué)地建立自己的技術(shù)體系和技術(shù)認(rèn)知!JAVA學(xué)習(xí)交流QQ群:288351179可以加群找我要課堂鏈接 注意:是免費(fèi)的 沒有開發(fā)經(jīng)驗(yàn)誤入哦! 非喜勿入扳躬!