1. 程式人生 > >關於Spring 中常用的那些設計模式

關於Spring 中常用的那些設計模式



Spring 中常用的設計模式 
1、我們通常說的 23 中經典設計模式可以通過下表一目瞭然:
 建立型 
工廠方法模式(FactoryMethod)、抽象工廠模式(AbstractFactory)、 建造者模式(Builder)、原型模式(Prototype)、單例模式(Singleton)
結構型
介面卡模式(Adapter)、橋接模式(Bridge)、組合模式(Composite)、 裝飾器模式(Decorator)、門面模式(Facade)、享元模式(Flyweight)、 代理模式(Proxy)
行為型
直譯器模式(Interpreter)、模板方法模式(TemplateMethod)、 責任鏈模式(ChainofResponsibility)、命令模式(Command)、 迭代器模式(Iterator)、調解者模式(Mediator)、備忘錄模式(Memento)、 觀察者模式(Observer)、狀態模式(State)、策略模式(Strategy)、 訪問者模式(Visitor)

通常來說,設計模式都是混合使用,不會獨立應用。利用窮舉法充分理解設計模式的應用場景。在平時 的應用中,不是用設計模式去生搬硬套,而是根據具體業務問題需要時借鑑。
 2、設計模式在應用中遵循六大原則:
 a、開閉原則(Open Close Principle) 開閉原則就是說對擴充套件開放,對修改關閉。在程式需要進行拓展的時候,不能去修改原有的程式碼,實現 一個熱插拔的效果。所以一句話概括就是:為了使程式的擴充套件性好,易於維護和升級。想要達到這樣的 效果,我們需要使用介面和抽象類,後面的具體設計中我們會提到這點。 
b、里氏代換原則(Liskov Substitution Principle) 里氏代換原則(Liskov Substitution Principle LSP)面向物件設計的基本原則之一。 里氏代換原 則中說,任何基類可以出現的地方,子類一定可以出現。 LSP 是繼承複用的基石,只有當衍生類可以 替換掉基類,軟體單位的功能不受到影響時,基類才能真正被複用,而衍生類也能夠在基類的基礎上增 加新的行為。里氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化。而 基類與子類的繼承關係就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規範。 
c、依賴倒轉原則(Dependence Inversion Principle) 這個是開閉原則的基礎,具體內容:針對介面程式設計,依賴於抽象而不依賴於具體。 
d、介面隔離原則(Interface Segregation Principle) 這個原則的意思是:使用多個隔離的介面,比使用單個介面要好。還是一個降低類之間的耦合度的意思, 從這兒我們看出,其實設計模式就是一個軟體的設計思想,從大型軟體架構出發,為了升級和維護方便。 所以上文中多次出現:降低依賴,降低耦合。 e、迪米特法則(最少知道原則)(Demeter Principle)
為什麼叫最少知道原則,就是說:一個實體應當儘量少的與其他實體之間發生相互作用,使得系統功能 模組相對獨立。 
f、合成複用原則(Composite Reuse Principle) 原則是儘量使用合成/聚合的方式,而不是使用繼承。 設計模式之間的關係圖


接下來我們只介紹在 Spring 中常用的設計模式。 
1.1、簡單工廠模式(Factory)
應用場景:又叫做靜態工廠方法(StaticFactory Method)模式,但不屬於 23 種設計模式之一。 簡單工廠模式的實質是由一個工廠類根據傳入的引數,動態決定應該建立哪一個產品類。 Spring 中的 BeanFactory 就是簡單工廠模式的體現,根據傳入一個唯一的標識來獲得 Bean 物件,但 是否是在傳入引數後建立還是傳入引數前建立這個要根據具體情況來定。

1.2、工廠方法模式(Factory Method)
應用場景:通常由應用程式直接使用 new 建立新的物件,為了將物件的建立和使用相分離,採用工廠模 式,即應用程式將物件的建立及初始化職責交給工廠物件。 一般情況下,應用程式有自己的工廠物件來建立 Bean.如果將應用程式自己的工廠物件交給 Spring 管 理,那麼 Spring 管理的就不是普通的 Bean,而是工廠 Bean。

1.3、單例模式(Singleton)
應用場景:保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點。 Spring 中的單例模式完成了後半句話,即提供了全域性的訪問點 BeanFactory。但沒有從構造器級別去 控制單例,這是因為 Spring 管理的是是任意的 Java 物件。 Spring 下預設的 Bean 均為單例。

常用單例模式寫法:餓漢式、懶漢式、註冊式、序列化。 
1.4、原型模式(Prototype)
 應用場景:原型模式就是從一個物件再建立另外一個可定製的物件,而且不需要知道任何建立的細節。 所謂原型模式,就是 Java 中的克隆技術,以某個物件為原型。複製出新的物件。顯然新的物件具備原 型物件的特點,效率高(避免了重新執行構造過程步驟)。

1.5、代理模式(Proxy)
應用場景:為其他物件提供一種代理以控制對這個物件的訪問。從結構上來看和 Decorator 模式類似, 但 Proxy 是控制,更像是一種對功能的限制,而 Decorator 是增加職責。 Spring 的 Proxy 模式在 AOP 中有體現,比如 JdkDynamicAopProxy 和 Cglib2AopProxy。

1.6、策略模式(Strategy)
應用場景:定義一系列的演算法,把它們一個個封裝起來,並且使它們可相互替換。本模式使得演算法可獨 立於使用它的客戶而變化。 Spring 中在例項化物件的時候用到 Strategy 模式,在 SimpleInstantiationStrategy 有使用。

1.7、模板方法模式(Template Method)
定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。Template Method 使得子類可以不改變 一個演算法的結構即可重定義該演算法的某些特定步驟。 TemplateMethod 模式一般是需要繼承的。這裡想要探討另一種對 TemplateMethod 的理解。Spring 中的 JdbcTemplate,在用這個類時並不想去繼承這個類,因為這個類的方法太多,但是我們還是想用 到 JdbcTemplate 已有的穩定的、公用的資料庫連線,那麼我們怎麼辦呢?我們可以把變化的東西抽出 來作為一個引數傳入 JdbcTemplate 的方法中。但是變化的東西是一段程式碼,而且這段程式碼會用到 JdbcTemplate 中的變數。怎麼辦?那我們就用回撥物件吧。在這個回撥物件中定義一個操縱 JdbcTemplate 中變數的方法,我們去實現這個方法,就把變化的東西集中到這裡了。然後我們再傳入 這個回撥物件到 JdbcTemplate,從而完成了呼叫。這就是 Template Method 不需要繼承的另一種實 現方式。

1.8、委派模式(Delegate)
應用場景:不屬於 23 種設計模式之一,是面向物件設計模式中常用的一種模式。這種模式的原理為類 B 和類 A 是兩個互相沒有任何關係的類,B 具有和 A 一模一樣的方法和屬性;並且呼叫 B 中的方法,屬性就是呼叫 A 中同名的方法和屬性。B 好像就是一個受 A 授權委託的中介。第三方的程式碼不需要知道 A 的 存在,也不需要和 A 發生直接的聯絡,通過 B 就可以直接使用 A 的功能,這樣既能夠使用到 A 的各種功 能,又能夠很好的將 A 保護起來了,一舉兩得。

1.9、介面卡模式(Adapter)
Spring AOP 模組對 BeforeAdvice、AfterAdvice、ThrowsAdvice 三種通知型別的支援實際上是借 助介面卡模式來實現的,這樣的好處是使得框架允許使用者向框架中加入自己想要支援的任何一種通知類 型,上述三種通知型別是 Spring AOP 模組定義的,它們是 AOP 聯盟定義的 Advice 的子型別。

1.10、裝飾器模式(Decorator)
應用場景:在我們的專案中遇到這樣一個問題:我們的專案需要連線多個數據庫,而且不同的客戶在每 次訪問中根據需要會去訪問不同的資料庫。我們以往在 Spring 和 Hibernate 框架中總是配置一個數據 源,因而 SessionFactory 的 DataSource 屬性總是指向這個資料來源並且恆定不變,所有 DAO 在使用 SessionFactory 的時候都是通過這個資料來源訪問資料庫。但是現在,由於專案的需要,我們的 DAO 在 訪問 SessionFactory 的時候都不得不在多個數據源中不斷切換,問題就出現了:如何讓 SessionFactory 在執行資料持久化的時候,根據客戶的需求能夠動態切換不同的資料來源?我們能不能 在 Spring 的框架下通過少量修改得到解決?是否有什麼設計模式可以利用呢? 
首先想到在 Spring 的 ApplicationContext 中配置所有的 DataSource。這些 DataSource 可能是各 種不同型別的,比如不同的資料庫:Oracle、SQL Server、MySQL 等,也可能是不同的資料來源:比如 Apache 提 供 的 org.apache.commons.dbcp.BasicDataSource 、 Spring 提 供 的 org.springframework.jndi.JndiObjectFactoryBean 等。然後 SessionFactory 根據客戶的每次 請求,將 DataSource 屬性設定成不同的資料來源,以到達切換資料來源的目的。 Spring 中用到的包裝器模式在類名上有兩種表現:一種是類名中含有 Wrapper,另一種是類名中含有 Decorator。基本上都是動態地給一個物件新增一些額外的職責。

1.11、觀察者模式(Observer)
應用場景:定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件 都得到通知並被自動更新。 Spring 中 Observer 模式常用的地方是 Listener 的實現。如 ApplicationListener。

1.12、各設計模式對比及程式設計思想總結 設計模式 一句話歸納 工廠模式

程式設計思想總結