更新時(shí)間:2021-04-26 11:37:25 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1106次
(1)適配器模式
適配器模式就是把一個(gè)類的接口變換成客戶端所能接受的另一種接口,從而使兩個(gè)接口不匹配而無法在一起工作的兩個(gè)類能夠在一起工作。通常被用在一個(gè)項(xiàng)目需要引用一些開源框架來一起工作時(shí),這些框架的內(nèi)部都有一些關(guān)于環(huán)境信息的接口,需要從外部引入,但是外部的接口不一定能匹配,在這種情況下,就需要適配器模式來轉(zhuǎn)換接口。
Java的I/O類庫(kù)中有許多這樣的需求,如將字符串轉(zhuǎn)成字節(jié)數(shù)據(jù)保存到文件中,將字節(jié)數(shù)據(jù)變成數(shù)據(jù)流等。具體來說,InputStreamReader和OutputStreamWriter就是適配器的體現(xiàn)。InputStreamReader實(shí)現(xiàn)了Reader接口,并且持有InputStream的引用,其作用是將InputStream適配到Reader。源角色就是InputStream代表的實(shí)例對(duì)象,目標(biāo)角色就是Reader類。OutputStreamWriter也是類似的方式。
(2)裝飾器模式
裝飾器的作用是使得被裝飾者功能更強(qiáng)大,而且裝飾前后的使用方式不變。Java I/O類庫(kù)中有許多不同的功能組合情況,這些不同的功能組合都是使用裝飾器模式實(shí)現(xiàn)的。以FileInputStream為例,其類結(jié)構(gòu)如下:
由于java I/O庫(kù)需要很多性能的各種組合,如果這些性能都是用繼承來實(shí)現(xiàn),那么每一種組合都需要一個(gè)類,這樣就會(huì)造成大量行重復(fù)的類出現(xiàn)。如果采用裝飾模式,那么類的數(shù)目就會(huì)大大減少,性能的重復(fù)也可以減至最少。因此裝飾模式是java I/O庫(kù)基本模式。裝飾模式的引進(jìn),造成靈活性和復(fù)雜性的提高。因此在使用 java I/O 庫(kù)時(shí),必須理解java I/O庫(kù)是由一些基本的原始流處理器和圍繞它們的裝飾流處理器所組成的。
InputStream類是以抽象組件的形式存在,而FileInputStream就是具體組件,它實(shí)現(xiàn)了抽象接口的所有方法,并且持有InputStream對(duì)象的引用。FileInputStream就是一個(gè)裝飾類,而BufferInputStream是這個(gè)裝飾類的具體實(shí)現(xiàn)者,它給InputStream加入了新的功能,使得InputStream讀取的數(shù)據(jù)保存在內(nèi)存中,從而提高讀取性能。
(3)適配模式和裝飾模式的區(qū)別
適配模式是為了處理兩個(gè)借口不一致,改變現(xiàn)有接口使其匹配。
裝飾模式是在不改變現(xiàn)有接口的前提下,加入新的功能。
javac 是java語言編程編譯器。全稱javacompilation。javac工具讀由java語言編寫的類和接口的定義,并將它們編譯成字節(jié)代碼的class文件。javac 可以隱式編譯一些沒有在命令行中提及的源文件。用 -verbose 選項(xiàng)可跟蹤自動(dòng)編譯。當(dāng)編譯源文件時(shí),編譯器常常需要它還沒有識(shí)別出的類型的有關(guān)信息。對(duì)于源文件中使用、擴(kuò)展或?qū)崿F(xiàn)的每個(gè)類或接口,編譯器都需要其類型信息。這包括在源文件中沒有明確提及、但通過繼承提供信息的類和接口。
Javac的編譯過程涉及許多語法分析,所有就有語法分析器、語義分析器和代碼生成器,期間需要多次遍歷語法樹。然而每次遍歷語法樹都會(huì)進(jìn)行不同的處理動(dòng)作,這是如何實(shí)現(xiàn)的呢?就是通過采用訪問者模式設(shè)計(jì)的,每次遍歷都是一次訪問者的執(zhí)行過程。
訪問者模式可以使數(shù)據(jù)結(jié)構(gòu)和對(duì)數(shù)據(jù)結(jié)構(gòu)的操作解耦,使得增加對(duì)數(shù)據(jù)結(jié)構(gòu)的操作不需要去修改數(shù)據(jù)結(jié)構(gòu),也不必去修改原有的操作,從而執(zhí)行時(shí)再定義新的Visitor實(shí)現(xiàn)者就行了。在Javac中不同的編譯階段都定義了不同的訪問者模式實(shí)現(xiàn)。
(1)門面模式
Tomcat中門面設(shè)計(jì)模式使用得很多,因?yàn)門omcat中有很多組件,每個(gè)組件要相互交互數(shù)據(jù),用門面設(shè)計(jì)模式隔離數(shù)據(jù)是個(gè)很好的方法。
可以看到,HttpRequestFacade類封裝了HttpRequest接口,能夠提供數(shù)據(jù),通過HttpRequestFacade訪問到的數(shù)據(jù)被代理到HttpReauest中、通常被封裝的對(duì)象都被設(shè)為Private或者Protectd的,防止在Facade中直接訪問。
(2)觀察者模式
Tomcat中觀察者模式也有多處使用,前面講的控制組件生命周期的Lifecycle就是這 種模式的體現(xiàn),還有對(duì)Servlet實(shí)例的創(chuàng)建、Session的管理、Container等都是同樣的原理。 下面主要看一下Lifecycle的具體實(shí)現(xiàn)。
Lifecycle的觀察者模式結(jié)構(gòu)圖如圖所示。
在上面的結(jié)構(gòu)圖中,LifecycleListener代表的是抽象觀察者,它定義一個(gè)lifecycleEvent 方法,這個(gè)方法就是當(dāng)主題變化時(shí)要執(zhí)行的方法。ServerLifecycleListener代表的是具體的 觀察者,它實(shí)現(xiàn)了 LifecycleListener接口的方法,就是這個(gè)具體的觀察者具體的實(shí)現(xiàn)方式。 Lifecycle接口代表的是抽象主題,它定義了管理觀察者的方法和它所要做的其他方法。而 StandardServer代表的是具體主題,它實(shí)現(xiàn)了抽象主題的所有方法。這里Tomcat對(duì)觀察者 做了擴(kuò)展,謂加了另外兩個(gè)類:LifecycleSupport和LifecycleEvent,它們作為輔助類擴(kuò)展 了觀察者的功能。LifecycleEvent使得可以定義事件類別,不同的事件可區(qū)別處理,更加靈活。LifecycleSupport類代理了主題對(duì)多觀察者的管理,將這個(gè)管理抽出來統(tǒng)一實(shí)現(xiàn),以 后如采修改只要修改LifecycleSupport類就可以了,不需要去修改所有的具體主題,因?yàn)?所有具體主題對(duì)觀察者的操作都被代理給LifecycleSupport類了。這可以認(rèn)為是觀察者模式的改進(jìn)版。
(3)命令設(shè)計(jì)模式
Tomcat中命令模式在Connector和Container組件之間有體現(xiàn),Tomcat作為一個(gè)應(yīng)用 服務(wù)器,無疑會(huì)接收到很多請(qǐng)求,如何分配和執(zhí)行這些請(qǐng)求是必須的功能。
下面分析一下Tomcat是如何實(shí)現(xiàn)命令模式的,下圖是Tomcat命令模式的結(jié)構(gòu)圖。
Connector作為抽象請(qǐng)求者,HttpConnector作為具體請(qǐng)求者。HttpProcessor作為命令。 Container作為命令的抽象接受者,ContainerBase作為具體的接受者。客戶端就是應(yīng)用服務(wù)器Server組件了。Server首先創(chuàng)建命令請(qǐng)求者HttpConnector對(duì)象,然后創(chuàng)建命令 HttpProcessor對(duì)象。再把命令對(duì)象交給命令接受者ContainerBase容器來處理,命令最終是被Tomcat的Container執(zhí)行的。命令可以以隊(duì)列的方式進(jìn)來,Container也可以以不同的 方式來處理請(qǐng)求,如HTTP1.0協(xié)議和HTTP1.1的處理方式就不同。
(4)責(zé)任鏈模式
Tomcat 中一個(gè)最容易發(fā)現(xiàn)的設(shè)計(jì)模式就是責(zé)任鏈設(shè)計(jì)模式,這個(gè)設(shè)計(jì)模式也是 Tomcat 中 Containe設(shè)計(jì)的基礎(chǔ),整個(gè)容器就是通過一個(gè)鏈連接在一起的,這個(gè)鏈一直將請(qǐng)求正確地傳遞給最終處理請(qǐng)求的那個(gè) Servlet 。在Tomcat中這種設(shè)計(jì)模式兒乎被完整地使用,Tomcat的容器設(shè)置就是責(zé)任鏈模式,從Engine到Host再到Cortex,一直到Wrapper都通過這個(gè)鏈傳遞請(qǐng)求。
(1)簡(jiǎn)單工廠模式
又叫做靜態(tài)工廠方法(StaticFactory Method)模式,但不屬于23種GOF設(shè)計(jì)模式之一。
簡(jiǎn)單工廠模式的實(shí)質(zhì)是由一個(gè)工廠類根據(jù)傳入的參數(shù),動(dòng)態(tài)決定應(yīng)該創(chuàng)建哪一個(gè)產(chǎn)品類。
spring中的BeanFactory就是簡(jiǎn)單工廠模式的體現(xiàn),根據(jù)傳入一個(gè)唯一的標(biāo)識(shí)來獲得bean對(duì)象,但是否是在傳入?yún)?shù)后創(chuàng)建還是傳入?yún)?shù)前創(chuàng)建這個(gè)要根據(jù)具體情況來定。如下配置,就是在 HelloItxxz 類中創(chuàng)建一個(gè) itxxzBean。
<beans>
<bean id="singletonBean" class="com.kang.HelloItxxz">
<constructor-arg>
<value>Hello! 這是singletonBean!value>
</constructor-arg>
</ bean>
<bean id="itxxzBean" class="com.kang.HelloItxxz"
singleton="false">
<constructor-arg>
<value>Hello! 這是itxxzBean! value>
</constructor-arg>
</bean>
</beans>
(2)工廠方法模式
通常由應(yīng)用程序直接使用new創(chuàng)建新的對(duì)象,為了將對(duì)象的創(chuàng)建和使用相分離,采用工廠模式,即應(yīng)用程序?qū)?duì)象的創(chuàng)建及初始化職責(zé)交給工廠對(duì)象。
一般情況下,應(yīng)用程序有自己的工廠對(duì)象來創(chuàng)建bean.如果將應(yīng)用程序自己的工廠對(duì)象交給Spring管理,那么Spring管理的就不是普通的bean,而是工廠Bean。
以工廠方法中的靜態(tài)方法為例講解一下:
import java.util.Random;
public class StaticFactoryBean {
public static Integer createRandom() {
return new Integer(new Random().nextInt());
}
}
建一個(gè)config.xm配置文件,將其納入Spring容器來管理,需要通過factory-method指定靜態(tài)方法名稱,createRandom方法必須是static的,才能找到
<bean id="random"
class="example.chapter3.StaticFactoryBean" factory-method="createRandom" scope="prototype"
/>
(3)單例模式
保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。
spring中的單例模式完成了后半句話,即提供了全局的訪問點(diǎn)BeanFactory。但沒有從構(gòu)造器級(jí)別去控制單例,這是因?yàn)閟pring管理的是是任意的java對(duì)象。 Spring下默認(rèn)的bean均為singleton,可以通過singleton=“true|false” 或者 scope=“?”來指定
(4)代理模式
在Spring的Aop中,使用的Advice(通知)來增強(qiáng)被代理類的功能。Spring實(shí)現(xiàn)這一AOP功能的原理就使用代理模式(1、JDK動(dòng)態(tài)代理。2、CGLib字節(jié)碼生成技術(shù)代理。)對(duì)類進(jìn)行方法級(jí)別的切面增強(qiáng),即,生成被代理類的代理類, 并在代理類的方法前,設(shè)置攔截器,通過執(zhí)行攔截器重的內(nèi)容增強(qiáng)了代理方法的功能,實(shí)現(xiàn)的面向切面編程。
(5)模板方法模式
定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
Template Method模式一般是需要繼承的。這里想要探討另一種對(duì)Template Method的理解。spring中的JdbcTemplate,在用這個(gè)類時(shí)并不想去繼承這個(gè)類,因?yàn)檫@個(gè)類的方法太多,但是我們還是想用到JdbcTemplate已有的穩(wěn)定的、公用的數(shù)據(jù)庫(kù)連接,那么我們?cè)趺崔k呢?我們可以把變化的東西抽出來作為一個(gè)參數(shù)傳入JdbcTemplate的方法中。但是變化的東西是一段代碼,而且這段代碼會(huì)用到JdbcTemplate中的變量。怎么辦?那我們就用回調(diào)對(duì)象吧。在這個(gè)回調(diào)對(duì)象中定義一個(gè)操縱JdbcTemplate中變量的方法,我們?nèi)?shí)現(xiàn)這個(gè)方法,就把變化的東西集中到這里了。然后我們?cè)賯魅脒@個(gè)回調(diào)對(duì)象到JdbcTemplate,從而完成了調(diào)用。這可能是Template Method不需要繼承的另一種實(shí)現(xiàn)方式吧。
(6)策略模式
Spring中的策略模式使用多如牛毛,所謂策略模式就是定義了算法族,分別封裝起來,讓他們之前可以互相轉(zhuǎn)換,此模式然該算法的變化獨(dú)立于使用算法的客戶。Spring的事務(wù)管理機(jī)制就是典型的策略模式,Spring事務(wù)策略是通過PlatformTransactionManager接口實(shí)現(xiàn)的,它是整個(gè)Spring事務(wù)的核心。它是對(duì)事務(wù)策略的一個(gè)高度抽象,不依賴于任何具體的事務(wù)策略,而對(duì)于底層的具體的事務(wù)策略它相應(yīng)的有不同的實(shí)現(xiàn)類。而對(duì)于不同的事務(wù)策略的切換通常由Spring容器來負(fù)責(zé)管理,應(yīng)用程序既無須與具體的事務(wù)API耦合,也無須與特定的實(shí)現(xiàn)類耦合而將應(yīng)用和持久化技術(shù),事務(wù)API徹底分離開來。
所謂模板模式就是定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。SpringMVC在保證整個(gè)框架流程穩(wěn)定的情況下,預(yù)留很多口子,而這些口子都是所謂的模板方法,可以自由指定,從而保證了靈活性,接下來的很多使用最佳實(shí)踐都是基于這種設(shè)計(jì)模式才可以實(shí)現(xiàn)。例如,下面的代碼中doResolveException(..)就是一個(gè)口子,子類方法doResolveException(..)可以定義具體如何處理異常。
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
if (shouldApplyTo(request, handler)) {
logException(ex, request);
prepareResponse(ex, response);
return doResolveException(request, response, handler, ex);
} else {
return null;
}
}
protected abstract ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex);
以上就是動(dòng)力節(jié)點(diǎn)小編介紹的“Java的設(shè)計(jì)模式常見應(yīng)用場(chǎng)景”的內(nèi)容,希望對(duì)大家有幫助,如有疑問,請(qǐng)?jiān)诰€咨詢,有專業(yè)老師隨時(shí)為您服務(wù)。
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時(shí)間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)
初級(jí) 202925
初級(jí) 203221
初級(jí) 202629
初級(jí) 203743