文章目錄
- 1:設計模式初探
- 1.1:什麼是設計模式
- 1.2 設計模式原則
- 1、開閉原則(Open Close Principle)
- 2、里氏代換原則(Liskov Substitution Principle)
- 3、依賴倒轉原則(Dependence Inversion Principle)
- 4、接口隔離原則(Interface Segregation Principle)
- 5、單一職責原則(Single Responsibility Principle)
- 6、最少知道原則(Demeter Principle)
- 7、合成複用原則(Composite Reuse Principle)
- 1.3:設計模式分類
- 1.4:常用設計模式
- 2:工廠模式
- 3:抽象工廠模式
1:設計模式初探
1.1:什麼是設計模式
在軟件工程中,設計模式是對軟件設計中普遍存在的各種問題,所提出的 解決方案。
換句話說,設計模式是一套被反覆使用、多數人知曉的、經過分類的、代碼設計的 經驗的總結。使用設計模式是爲了可重用代碼,讓代碼更容易被他人理解,保證代碼可靠性。
1.2 設計模式原則
1、開閉原則(Open Close Principle)
開閉原則的意思是:對擴展開放,對修改封閉。在程序需要進行擴展的時候,不能去修改或影響原有的代碼,實現一個熱插拔的效果。簡言之,是爲了使程序的擴展性更好,易於維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類。
2、里氏代換原則(Liskov Substitution Principle)
里氏代換原則是面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。里氏代換原則是繼承複用的基石,只有當子類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被複用,而且子類也能夠在基類的基礎上增加新的行爲。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關係就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規範。
3、依賴倒轉原則(Dependence Inversion Principle)
這個原則是開閉原則的基礎,核心內容:針對接口編程,高層模塊不應該依賴底層模塊,二者都應該依賴抽象而不依賴於具體。
4、接口隔離原則(Interface Segregation Principle)
這個原則的意思是:使用多個隔離的接口,比使用單個龐大的接口要好。其目的在於降低耦合度。由此可見,其實設計模式就是從大型軟件架構出發,便於升級和維護軟件的設計思想。它強調低依賴、低耦合。
5、單一職責原則(Single Responsibility Principle)
類的職責要單一,不能將太多的職責放在一個類中。
可能有的人會覺得單一職責原則和前面的接口隔離原則很相似,其實不然。其一,單一職責原則原注重的是職責;而接口隔離原則注重對接口依賴的隔離。其二,單一職責原則主要約束的是類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口,主要針對抽象,針對程序整體框架的構建。
6、最少知道原則(Demeter Principle)
最少知道原則也叫迪米特法則,就是說:一個實體應當儘量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
一個對象應該對其他對象保持最少的瞭解。類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。如果兩個類不必彼此直接通信,那麼這兩個類就不應當發生直接的相互作用。如果其中一個類需要調用另一個類的某一個方法的話,可以通過第三者轉發這個調用。所以在類的設計上,每一個類都應當儘量降低成員的訪問權限。
7、合成複用原則(Composite Reuse Principle)
合成複用原則就是在一個新的對象裏通過關聯關係(組合關係、聚合關係)來使用一些已有的對象,使之成爲新對象的一部分;新對象通過委派調用已有對象的方法達到複用功能的目的。簡而言之,儘量多使用 組合/聚合 的方式,儘量少使用甚至不使用繼承關係。
1.3:設計模式分類
通常來說設計模式分爲三大類:
創建型模式,共 5 種:工廠模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共 7 種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行爲型模式,共 11 種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
下面這張圖表示模式間的關係
1.4:常用設計模式
在以後的課程中,我們會逐步講解常用的設計模式,包括 工廠模式、單例模式、適配器模式、觀察者模式等等。
2:工廠模式
2.1:什麼是工廠模式
工廠模式(Factory Pattern)的意義就跟它的名字一樣,在面向對象程序設計中,工廠通常是一個用來創建其他對象的對象。工廠模式根據不同的參數來實現不同的分配方案和創建對象。
在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且是通過使用一個共同的接口來指向新創建的對象。例如用工廠來創建 人 這個對象,如果我們需要一個男人對象,工廠就會爲我們創建一個男人;如果我們需要一個女人,工廠就會爲我們生產一個女人。
工廠模式通常分爲:
普通工廠模式
多個工廠方法模式
靜態工廠方法模式
2.2:普通工廠模式
剛剛我們說到,用工廠模式來創建人。先創建一個男人,他每天都 “喫飯、睡覺、打豆豆”,然後我們再創建一個女人,她每天也 “喫飯、睡覺、打豆豆”。
我們以普通工廠模式爲例,在project目錄下新建一個
FactoryTest.java。
示例代碼如下(下面的代碼塊中是全部的代碼,實際操作中應當按註釋創建相應的類再將方法寫入對應的類中):
// 二者共同的接口
interface Human{
public void eat();
public void sleep();
public void beat();
}
// 創建實現類 Male
class Male implements Human{
public void eat(){
System.out.println("Male can eat.");
}
public void sleep(){
System.out.println("Male can sleep.");
}
public void beat(){
System.out.println("Male can beat.");
}
}
//創建實現類 Female
class Female implements Human{
public void eat(){
System.out.println("Female can eat.");
}
public void sleep(){
System.out.println("Female can sleep.");
}
public void beat(){
System.out.println("Female can beat.");
}
}
// 創建普通工廠類
class HumanFactory{
public Human createHuman(String gender){
if( gender.equals("male") ){
return new Male();
}else if( gender.equals("female")){
return new Female();
}else {
System.out.println("請輸入正確的類型!");
return null;
}
}
}
// 工廠測試類
public class FactoryTest {
public static void main(String[] args){
HumanFactory factory = new HumanFactory();
Human male = factory.createHuman("male");
male.eat();
male.sleep();
male.beat();
}
}
打開terminal,輸入命令編譯並運行:
javac FactoryTest.java
java FactoryTest
運行結果
2.3:多個工廠方法模式
普通工廠模式就是上面那樣子了,那麼多個工廠方法模式又有什麼不同呢?在普通工廠方法模式中,如果傳遞的字符串出錯,則不能正確創建對象。多個工廠方法模式是提供多個工廠方法,分別創建對象。
部分示例代碼,其他與上面普通工廠模式示例代碼一樣:
// 多個工廠方法
public class HumanFactory{
public Male createMale() {
return new Male();
}
public Female createFemale() {
return new Female();
}
}
// 工廠測試類
public class FactoryTest {
public static void main(String[] args){
HumanFactory factory = new HumanFactory();
Human male = factory.createMale();
male.eat();
male.sleep();
male.beat();
}
}
運行結果與單個工廠相同
2.4:靜態工廠模式:
將上面的多個工廠方法模式裏的方法置爲靜態的,不需要創建實例,直接調用即可。
部分示例代碼:
// 多個工廠方法
public class HumanFactory{
public static Male createMale() {
return new Male();
}
public static Female createFemale() {
return new Female();
}
}
// 工廠測試類
public class FactoryTest {
public static void main(String[] args){
Human male = HumanFactory.createMale();
male.eat();
male.sleep();
male.beat();
}
}
總結:凡是出現了大量的產品需要創建,並且具有共同的接口時,可以通過工廠方法模式進行創建。在以上的三種模式中,第一種如果傳入的字符串有誤,不能正確創建對象,第三種相對於第二種,不需要實例化工廠類,所以,大多數情況下,我們會選用第三種——靜態工廠方法模式。
2.5:工廠模式應用
你可能就問了,工廠模式工廠模式的,我咋沒見過哪兒用過啊?這這這兒,在 Java 庫裏面。根據不同的參數,getInstance() 方法會返回不同的 Calendar 對象。
java.util.Calendar - getInstance()
java.util.Calendar - getInstance(TimeZone zone)
java.util.Calendar - getInstance(Locale aLocale)
java.util.Calendar - getInstance(TimeZone zone, Locale aLocale)
java.text.NumberFormat - getInstance()
java.text.NumberFormat - getInstance(Locale inLocale)
寫 Android 的童鞋們,應該還知道 BitmapFactory , 這也是工廠模式的一種應用。
3:抽象工廠模式
3.1:什麼是抽象工廠模式
抽象工廠模式(Abstract Factory Pattern)是一種軟件開發設計模式。抽象工廠模式提供了一種方式,可以將一組具有同一主題的單獨的工廠封裝起來。如果比較抽象工廠模式和工廠模式,我們不難發現前者只是在工廠模式之上增加了一層抽象的概念。抽象工廠是一個父類工廠,可以創建其它工廠類。所以我們也叫它 “工廠的工廠”。(想想上節課的 “女媧娘娘”,這簡直就是 “女媧娘娘的親孃” 啊…)
3.2:抽象工廠的類圖
“女媧娘娘”只有一個,而我們的工廠卻可以有多個,因此在這裏用作例子就不合適了。作爲“女媧娘娘”生產出來的男人女人們,那就讓我們來當一次喫貨吧。(喫的東西總可以任性多來一點…)
現在,假設我們有 A、B 兩個廚房。每個廚房擁有的餐具和食品都不一樣,但是用戶搭配使用的方式,比如刀子和蘋果、杯子和牛奶等等,我們假設是一致的。