OOAD之設計模式
一、模式:
避免重複問題,而提出來的解決方案。
模式又可以分為:
架構模式
設計模式
1.1架構模式
軟體架構的上,整體考慮,而提出來的一些解決方案,比如:三層架構,B/S,C/S,MVC,ORM,事務指令碼,領域模型……,從巨集觀的角度上來說
1.2設計模式
設計模式是從微觀的角度上來看待軟體開發過程中,碰到的一些重複業務場景,並提出的解決方案。
設計模式:建立性設計模式,結構性設計模式,行為性設計模式
**建立性設計模式:**更多的關注物件如何建立,而提出來的各種建立方案
**結構性設計模式:**更多的關注於類和類,物件和物件的整體結構,而提出來的各種解決方案
**行為性設計模式:**更多的關注於例項之間的行為互調,以及職責分配的問題
1.2.1分類
*建立性設計模式中:**
簡單工廠模式
靜態工廠方法(Static Factory Method)
抽象工廠(Abstract Factory)
單例模式(Singleton)
原型模式(Prototype)
建造模式(Builder)
**結構性設計模式中:**
介面卡模式(Adapter)
橋接模式(Bridge)
複合模式(Composite)
裝飾器模式(Decorator)
外觀模式(Façade)
享元模式(FlyWeight)
代理模式(Proxy)
**行為性設計模式:**
直譯器模式(Interpreter)
模板方法模式(Template Method)
職責鏈模式(Chain of Responsibility)
命令模式(Command)
迭代器模式(Iterator)
中介者模式(Mediator)
備忘錄模式(Memento)
觀察者模式(Observer)
策略模式(Strategy)
狀態模式(State)
訪問者模式(Visitor)
1.2.1詳細介紹
**1、簡單工廠模式**
簡單工廠模式,又被稱之為“靜態工廠方法”模式,該模式會專門定義一個“工廠類”,然後在工廠類提供一個靜態方法,有該靜態方法根據使用者的輸入,動態決定建立什麼型別的物件。通常來說:工廠類的產生的物件,都有一個特點,具備相同的父類,或者具備相同的介面
簡單工廠的3種角色:工廠類,產品的抽象類(介面),具體的產品
1)工廠類:主要負責根據使用者的輸入,動態的產生具體的產品
2)產品抽象類|介面:對具體產品進行類的抽象或者行為的抽象
3)具體的產品:工廠類產生的具體例項
簡單工廠模式的作用:
將客戶呼叫類上的2個職責(建立物件的職責,呼叫物件的行為的職責),進行職責分離,讓呼叫類最終只存在1個職責(呼叫物件的行為的職責),而將建立物件的職責,委託給工廠類。
簡單工廠模式的缺點:
簡單工廠,實際上將物件的產生,由之前的客戶呼叫類身上,強制性的定義在工廠類身上,工廠類此時具備一定的建立物件的業務邏輯,以及一些判斷邏輯。那麼如果具體的產品,需要發生變化,或者有新的產品需要擴充套件,那麼毫無疑問,此時就需要去針對工廠類做相應的變化,那麼無形當中就違背了“開閉原則”,“單一原則”,“依賴倒轉原則”
注意:
簡單工廠模式,只能產生同一家族(繼承相同類,實現相同介面)的產品,非同一家族的產品,簡單工廠是無法使用的。
**2、抽象工廠方法模式:**
簡單工廠模式,會出現一些問題,比如:呼叫類和工廠類直接耦合(依賴倒轉原則),工廠類中無法滿足“開閉原則”,因為工廠類中方法存在一定的業務邏輯和判斷邏輯,如果需要新增新的產品,工廠類也需要去做相應的修改,所以違背了“開閉原則”
為了規避上述問題,所以才有了抽象工廠方法模式,該模式實際上就是在工廠類的基礎上,進一步進行工廠抽象,然後每一個獨立的產品,都對應一個具體的產品工廠,通過這種方式來實現程式滿足“開閉原則”
在呼叫類中使用面向介面程式設計,來解決上述的呼叫類和工廠類直接耦合的問題。
抽象工廠模式有4種角色:
1、工廠的抽象類 完成對產品生產工廠進行抽象
2、具體產品的生產工廠 分別對產品進行生產
3、產品抽象類|介面:對具體產品進行類的抽象或者行為的抽象
4、具體的產品:工廠類產生的具體例項
**3、原型模式(克隆模式):**
原型模式:如果某一個類存在大量的屬性,然後又需要大量產生該類的相同或者相似的物件的時候,我們就可以使用克隆模式。克隆就是指以什麼東西作為參照,大量產生新的物件。
如果大量的物件在產生的時候,大部分的屬性或者絕大多數的屬性都一樣,而只有少量的屬性存在差異時,此時,我們就可以使用原型模式。
JAVA中原型模式,實現方式非常簡單:實現Cloneable介面,並重寫clone()就可以完成物件的“淺克隆”,如果物件的關聯物件也需要克隆的話,那麼就需要關聯物件也要實現實現Cloneable介面,並重寫clone(),並且物件克隆時,還要通知關聯物件也去克隆,從而做到“深度克隆”。
例子:
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
//加了下面這句話,就叫深度克隆
this.setWife((Wife)wife.clone());
return super.clone();
}
**4、單例模式:**
單例模式:如果碰到某種業務場景,如果一個類在整個軟體範圍內,都只需要擁有1個例項的時候,我們就可以使用單例模式。
例如:多臺電腦,對應1臺印表機,那麼印表機在區域網範圍內,就只有1個單例項
單例項的實現方式
懶漢式:
/**
* 懶漢,執行緒不安全版 1.0版本
* @return
*/
public static RandomSingleton getInstance() {
if (instance == null) {
instance = new RandomSingleton();
}
return instance;
}
/**
* 懶漢,執行緒安全版2.0版本
* @return
*/
public static RandomSingleton getInstance() {
synchronized (instance) {
if (instance == null) {
instance = new RandomSingleton();
}
return instance;
}
}
/**
* 懶漢,執行緒安全版2.2版本
* 雙重檢測機制
* @return
*/
public static LazyManSingleton getInstance() {
if (instance == null) {
//1,2,3,4……所有的執行緒
synchronized (LazyManSingleton.class) {
if(instance == null) {
instance = new LazyManSingleton();
}
}
}
return instance;
}
餓漢式:
/**
* 單例模式(餓漢式)
* @author Administrator
*/
public class HungryManSingleton {
private static HungryManSingleton instance = new HungryManSingleton();
private HungryManSingleton() {
// TODO Auto-generated constructor stub
}
/**
* 天生就是執行緒安全的
* @return
*/
public static HungryManSingleton getInstance() {
return instance;
}
}
推薦大家,直接使用餓漢式記住:沒有痴漢式,飽漢式……
**5、介面卡模式:**
當兩個類 ,或者說兩個元件需要相互通訊的時候,然後兩個類又無法直接互動的情況下,比如:美國教練無法直接指揮外籍球員“何憨鋒”時,“何憨鋒”聽不懂英文,那麼此時就需要一個介面卡|翻譯員,來幫我們做一箇中間翻譯,或者適配的工作!
**6、觀察者模式:**
比如:大家在上高中的時候,一大幫觀察老師的情況
比如:商家的貨品在降價時,自動通知所有關注該商品的使用者
觀察者模式,定義了一種1對多的依賴關係,讓多個觀察者物件同時監聽|觀察同一個主題,當主題的狀態發生變化的時候,可以讓這些多個觀察者自動重新整理他們自己。當然這個過程,是由主題來通知觀察者發生
如下面這個檔案表結構:
observer檔案下的Observer抽象類(觀察者)、Subject抽象類(被觀察者)、MainEnter是測試用的;
impl子檔案下的Teacher類(被觀察者)繼承了Subject抽象類(被觀察者),PlayGameStudent、ReadNovelStudent、SeePhoneStudent是繼承了Observer抽象類(觀察者);
在上面中,老師是被觀察者,同學們是觀察者。
老師類中有個狀態屬性,當被觀察者老師的狀態改變後,需要通過老師類中的告知方法,去告知同學自己的狀態發生了改變,然後同學去執行相應動作。
在老師類中有個集合用於裝下所有不同的同學;
再告知方法中,通過判斷老師目前的狀態,然後在狀態特定的情況下才去執行同學帶有的方法,比如看小說等等,同學們的這些行為都是繼承於他們的抽象類,只是不同的實現。通過foreach迴圈方法就可把集合中的同學得到,然後執行同學類的方法。
**7、代理模式**
代理模式給某一個物件提供一個代理物件,並由代理物件控制對原物件的引用。通俗的來講代理模式就是我們生活中常見的中介。
舉個例子來說明:假如說我現在想買一輛二手車,雖然我可以自己去找車源,做質量檢測等一系列的車輛過戶流程,但是這確實太浪費我得時間和精力了。我只是想買一輛車而已為什麼我還要額外做這麼多事呢?於是我就通過中介公司來買車,他們來給我找車源,幫我辦理車輛過戶流程,我只是負責選擇自己喜歡的車,然後付錢就可以了。用圖表示如下:
為什麼要用代理模式?
中介隔離作用:在某些情況下,一個客戶類不想或者不能直接引用一個委託物件,而代理類物件可以在客戶類和委託物件之間起到中介的作用,其特徵是代理類和委託類實現相同的介面。
開閉原則,增加功能:代理類除了是客戶類和委託類的中介之外,我們還可以通過給代理類增加額外的功能來擴充套件委託類的功能,這樣做我們只需要修改代理類而不需要再修改委託類,符合程式碼設計的開閉原則。代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後對返回結果的處理等。代理類本身並不真正實現服務,而是同過呼叫委託類的相關方法,來提供特定的服務。真正的業務功能還是由委託類來實現,但是可以在業務功能執行的前後加入一些公共的服務。例如我們想給專案加入快取、日誌這些功能,我們就可以使用代理類來完成,而沒必要開啟已經封裝好的委託類。
有哪幾種代理模式?
我們有多種不同的方式來實現代理。如果按照代理建立的時期來進行分類的話, 可以分為兩種:靜態代理、動態代理。靜態代理是由程式設計師建立或特定工具自動生成原始碼,在對其編譯。在程式設計師執行之前,代理類.class檔案就已經被建立了。動態代理是在程式執行時通過反射機制動態建立的。
**8、備忘錄模式**
如果某一天,我們存在需要對某一個物件的狀態進行備份的時候,我們就可以去使用“備忘錄模式”,備忘錄模式,要求在不破壞原有物件的封裝的基礎上,讓另外一個物件去記錄原物件的所有狀態,如果某一天,原物件的狀態存在丟失的情況,需要還原時,我們就可以採用另外的物件來進行還原。
備忘錄模式中,存在以下角色:
原物件:它是備份資料的發起者
備忘錄物件:記錄原物件的資料
備忘錄管理者物件:管理備忘錄物件
**9、建造者模式**
當生產的產品,具有固定的建造步驟時,就需要大家去使用建造者模式,建造者模式的主要作用:是將物件的生產與物件的行為表現分離,無論你產生的是什麼型別的產品,反正在建造類中都是使用的固定的建造的步驟。建造者模式更多的是用於:封裝某一個具有多個元件組成的產品,比如:電腦,汽車,機器人……
你在生產具有多個元件的產品時,又不想讓其他人知道你詳細的建造過程時,你就可以用建造者模式。
**10、裝飾器模式**
當需要給某一個物件,動態新增更多的責任的時候,我們就可以使用裝飾器模式,比如:給小峰峰穿衣服
裝飾的時候,是一層層的裝飾,比如:
//要給小峰峰穿衣服,裝扮
tx.decorate(person);
ld.decorate(tx);
dk.decorate(ld);
htg.decorate(dk);
**11、責任鏈模式**
使用場景,稍微要多一些,一般發生在公司具有審批流程時,根據輸入的請求條件,來動態的決定由哪一個上級來處理該請求。如果領導沒有權利處理請求的話,可以直接拋給上級,讓上級接著處理。
責任鏈模式中:一定要確定好上下級關係,以及每一個領導自身所具備的權利大小。
**12、抽象工廠模式**
使用場景:現在系統中,存在多套系列的產品,比如:即存在mysql資料庫的產品,又存在SQLServer資料庫的產品,那麼如果做到2套產品之後,可以動態切換,那麼就需要使用到“抽象工廠模式”。