Java程式設計師從笨鳥到菜鳥(三十二)23種設計模式之工廠模式
設計模式的六大原則
開閉原則
是最基礎的設計原則,其它的五個設計原則都是開閉原則的具體形態,依照java的語言的稱謂,開閉原則是抽象類,其它的五個原則是具體實現類
開閉原則
:軟體實體應當對外擴充套件開放,對修改關閉,通俗點說就是應該在不修改原有程式碼的基礎上,引入新功能。為了使程式的擴充套件性好,易於維護和升級
詳細解釋見百度百科開閉原則
實現方法:關鍵在於抽象,把系統所有的可能的行為抽象成一個抽象層,這個抽象底層規定出所有的具體實現必須提供的方法的特徵,作為系統設計的抽象層,要預見所有可能的擴充套件,從而使得在任何擴充套件情況下,系統的抽象底層不需修改;同時,由於可以從抽象底層匯出一個或多個新的具體實現,可以改變系統的行為,因此係統設計對擴充套件是開放的
單一職責原則
不要存在多於一個導致類變更的原因,也就是說每個類應該實現單一的職責,否則就應該把類拆分
里氏替換原則
里氏代換原則是對“開-閉”原則的補充。實現“開閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關係就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規範。里氏替換原則中,子類對父類的方法儘量不要重寫和過載。因為父類代表了定義好的結構,通過這個規範的介面與外界互動,子類不應該隨便破壞它
依賴倒轉原則
面向介面程式設計,依賴於抽象而不依賴於具體
介面隔離原則
每個介面中不存在子類用不到卻必須實現的方法,如果不然,就要將介面拆分。使用多個隔離的介面,比使用單個介面(多個介面方法集合到一個的介面)要好
迪米特原則(最少知道原則)
一個類對自己依賴的類知道的越少越好,無論被依賴的類多麼複雜,都應該將邏輯封裝在方法的內部,通過public方法提供給外部,這樣當被依賴的類變化時,才能最小的影響該類
模式
在面向物件程式設計中, 最通常的方法是一個new操作符產生一個物件例項,new操作符就是用來構造物件例項的,但是在一些情況下, new操作符直接生成物件會帶來一些問題。舉例來說, 許多型別物件的創造需要一系列的步驟: 你可能需要計算或取得物件的初始設定; 選擇生成哪個子物件例項; 或在生成你需要的物件之前必須先生成一些輔助功能的物件。 在這些情況,新物件的建立就是一個 “過程”,不僅是一個操作,像一部大機器中的一個齒輪傳動。
模式的問題:你如何能輕鬆方便地構造物件例項,而不必關心構造物件例項的細節和複雜過程呢?
解決方案:建立一個工廠來建立物件
實現
1.還沒有工廠時代:接入沒有革命,客戶需要一輛寶馬,通常做法是客戶建立一輛寶馬
2.簡單工廠模式:後來出現工業革命,使用者不用自己取建立寶馬車,有一個工廠來幫他建立寶馬車,想要什麼車,直接工廠就能建成
3.工廠方法模式:為了滿足客戶,寶馬系列越來越多,一個工廠不能實現生產所有的系列,於是單獨分出來具體的工廠,每個工廠負責一個系列,具體工廠類只能建立一個產品,但是寶馬工廠還是抽象類,需要制定某個具體的工廠才能生產出來。
4.抽象工廠模式:隨著客戶要求越來越高,寶馬車必須配置空調
最終客戶對銷售員說需要一輛有空調的寶馬,就不需要自己去建立,這就是工廠模式
分類
工廠模式主要為建立物件提供過度介面,以便將建立物件的具體過程遮蔽隔離起來,達到提供靈活性,工廠模式可分為三類:
- 簡單工廠模式
- 工廠方法模式
- 抽象工廠模式
通常將簡單工廠模式看成是工廠方法的特例。
區別
工廠方法模式:
一個抽象產品類,可以派生出多個具體產品類
一個抽象工廠類,可以派生出多個具體工廠類
每個具體工廠類只能建立一個具體產品類的例項
抽象工廠模式
多個抽象產品類,每個抽象產品類可以派生出多個具體產品類
一個抽象工廠類,可以派生出多個具體工廠
每個具體工廠類可以建立多個具體產品類的例項
區別:
工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個
工廠方法模式的具體工廠類只能建立一個具體產品類的例項,而抽象工廠模式可以建立多個
簡單工廠模式
建立一個工廠類方法
來製造新的物件:
程式碼實現
產品類:
abstract class BMW {
public BMW() {
}
}
class BMW320 extends BMW {
public BMW320() {
System.out.println("簡單工廠模式...製造BMW320");
}
}
class BMW523 extends BMW {
public BMW523() {
System.out.println("簡單工廠模式...製造BMW523");
}
}
工廠類:
public class Factory {
public BMW createBMW(int type) {
switch (type) {
case 320:
return new BMW320();
case 523:
return new BMW523();
default:
break;
}
return null;
}
}
客戶類:
public class Customer {
public static void main(String[] args) {
Factory fatcory = new Factory();
BMW bmw320 = fatcory.createBMW(320);
BMW bmw523 = fatcory.createBMW(523);
}
}
執行結果:
簡單工廠模式...製造BMW320
簡單工廠模式...製造BMW523
Process finished with exit code 0
簡單工廠模式又稱靜態工廠模式,定義一個用於建立物件的介面
組成:
- 工廠類:模式核心,具有判斷業務邏輯,用來建立產品
- 抽象產品:具有產品繼承的父類或者實現的介面
- 具體產品:工廠類所建立的物件就是例項,由一個具體類實現
簡單工廠模式只有一個類來對應產品,工廠類也叫全能類,對於這種侷限,不利於擴充套件和維護,工廠方法模式就出現了
工廠方法模式
工廠方法模式
去掉了簡單工廠模式方法的靜態屬性,使得可以被子類繼承,這樣集中在工廠類處理的壓力就可以由工廠方法模式裡的不同子類來分擔
組成:
- 抽象工廠:模式核心,是具體工廠角色必須實現的介面或者必須繼承的父類。在java中它由抽象類或者介面來實現
- 具體工廠:含有和具體業務邏輯有關的程式碼。由應用程式呼叫以建立對應的具體產品的物件
- 抽象產品:是具體產品繼承的父類或者是實現的介面
- 具體產品:具體工廠角色所建立的物件就是此角色的例項
工廠方法模式使用繼承自抽象工廠角色的多個子類來替代簡單工廠模式的全能類,這樣使結構更加靈活
程式碼實現
產品類:
abstract class BMW {
public BMW() {
}
}
class BMW320 extends BMW {
public BMW320() {
System.out.println("工廠方法模式...製造BMW320");
}
}
class BMW523 extends BMW {
public BMW523() {
System.out.println("工廠方法模式...製造BMW523");
}
}
工廠類:
interface FactoryBMW {
BMW createBMW();
}
class FactoryBMW320 implements FactoryBMW {
@Override
public BMW320 createBMW() {
return new BMW320();
}
}
class FactoryBMW523 implements FactoryBMW {
@Override
public BMW523 createBMW() {
return new BMW523();
}
}
客戶類:
public class Customer {
public static void main(String[] args) {
FactoryBMW320 factoryBMW320 = new FactoryBMW320();
BMW320 bmw320 = factoryBMW320.createBMW();
FactoryBMW523 factoryBMW523 = new FactoryBMW523();
BMW523 bmw523 = factoryBMW523.createBMW();
}
}
執行結果:
工廠方法模式...製造BMW320
工廠方法模式...製造BMW523
Process finished with exit code 0
工廠方法模式對物件的建立進行了包裝
抽象工廠模式
一般用於具有產品樹(產品層次結構)和產品族的場景下
例子背景:
隨著客戶的要求越來越高,寶馬車需要不同配置的空調和發動機等配件。於是這個工廠開始生產空調和發動機,用來組裝汽車。這時候工廠有兩個系列的產品:空調和發動機。寶馬320系列配置空調和發動機,寶馬230系列配置空調和發動機
概念
抽象工廠模式是工廠模式的升級版,用來建立一組相關或者相互依賴的物件,例如寶馬320使用的電機和空調型號,寶馬523使用的另外的型號,就需要使用工廠模式,在生產320系列時候就不需要執行型號進行生產.每個抽象產品都有兩個具體的產品
抽象工廠模式和工廠方法模式的區別
在於需要建立物件的複雜程度上,抽象工廠模式是三個裡面最抽象,最具一般性的,給客戶端提供一個介面,可以建立多個產品族中的產品物件
使用抽象工廠模式需要滿足條件:
1.系統中有多個產品族,而系統一次只能消費其中的一族產品
抽象工廠模式的各個角色:
抽象工廠角色:方法的核心,是具體工廠角色必須實現的介面或繼承的父類,在java中由抽象類或介面來實現
具體工廠角色:含有和具體業務邏輯相關的程式碼,由應用程式呼叫對應具體產品的物件,在java中由具體的類來實現
抽象產品角色:具體產品繼承的父類或者實現的介面,在java中一般由抽象類和介面來實現
具體產品角色:具體工廠角色所建立的物件就是此角色,在java中一般由具體的類來實現
程式碼實現
產品類:
Engine抽象類
// 抽象產品
public abstract class Engine {
}
// 具體產品
class Engine320 extends Engine {
public Engine320() {
System.out.println("抽象工廠模式...製造Engine320");
}
}
class Engine523 extends Engine {
public Engine523() {
System.out.println("抽象工廠模式...製造Engine523");
}
}
AirCondition抽象類
// 抽象產品
public abstract class AirCondition {
}
// 具體產品
class AirCondition320 extends AirCondition {
public AirCondition320() {
System.out.println("抽象工廠模式...製造AirCondition320");
}
}
class AirCondition523 extends AirCondition {
public AirCondition523() {
System.out.println("抽象工廠模式...製造AirCondition523");
}
}
工廠類:
// 抽象工廠
public interface AbstractFactory {
public Engine createEngine(); // 製造發動機
public AirCondition createAirCondition(); // 製造空調
}
// 具體工廠
// 為寶馬320系列生產配件
class FactoryBMW320 implements AbstractFactory {
@Override
public Engine createEngine() {
return new Engine320();
}
@Override
public AirCondition createAirCondition() {
return new AirCondition320();
}
}
// 為寶馬523系列生產配件
class FactoryBMW523 implements AbstractFactory {
@Override
public Engine createEngine() {
return new Engine523();
}
@Override
public AirCondition createAirCondition() {
return new AirCondition523();
}
}
客戶類:
public class Customer {
public static void main(String[] args) {
// 生產寶馬320系列配件
FactoryBMW320 factoryBMW320 = new FactoryBMW320();
factoryBMW320.createEngine();
factoryBMW320.createAirCondition();
// 生產寶馬523系列配件
FactoryBMW523 factoryBMW523 = new FactoryBMW523();
factoryBMW523.createEngine();
factoryBMW523.createAirCondition();
}
}
執行結果:
抽象工廠模式...製造Engine320
抽象工廠模式...製造AirCondition320
抽象工廠模式...製造Engine523
抽象工廠模式...製造AirCondition523
Process finished with exit code 0
相關推薦
Java程式設計師從笨鳥到菜鳥(三十二)23種設計模式之工廠模式
設計模式的六大原則 開閉原則是最基礎的設計原則,其它的五個設計原則都是開閉原則的具體形態,依照java的語言的稱謂,開閉原則是抽象類,其它的五個原則是具體實現類 開閉原則:軟體實體應當對外擴充套件開放,對修改關閉,通俗點說就是應該在不修改原有程式碼的
Python之路(三十二):DjangoModel補充 Django之Model進階的更多操作 Django之Model進階的更多操作
Django之Model進階的更多操作 一、欄位 AutoField(Field) - int自增列,必須填入引數 primary_key=True BigAutoField(
Java程式設計師從笨鳥到菜鳥之(三十二)大話設計模式(二)設計模式分類和三種工廠模式
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
笨辦法學Python(三十一)
raw 冒險遊戲 utils splay oba log through nested cut 習題 31: 作出決定 這本書的上半部分你打印了一些東西,而且調用了函數,不過一切都是直線式進行的。你的腳本從最上面一行開始,一路運行到結束,但其中並沒有決定程序流向的分
笨辦法學Python(三十七)
相等 tar .com except com lam 返回 final 每一個 習題 37: 復習各種符號 現在該復習你學過的符號和 python 關鍵字了,而且你在本節還會學到一些新的東西。我在這裏所作的是將所有的 Python 符號和關鍵字列出來,這些都是值得掌
笨辦法學Python(三十六)
有時 就會 ast 區分 對待 似的 pre 並且 寫代碼 習題 36: 設計和調試 現在你已經學會了“if 語句”,我將給你一些使用“for 循環”和“while 循環”的規則,一面你日後碰到麻煩。我還會教你一些調試的小技巧,以便你能發現自己程序的問題。最後,你將
笨辦法學Python(三十九)
hone img simple all 上網 其中 如果 參數 它的 習題 39: 列表的操作 你已經學過了列表。在你學習“while 循環”的時候,你對列表進行過“追加(append)”操作,而且將列表的內容打印了出來。另外你應該還在加分習題裏研究過 Python
Java基礎系列(三十二):斷言 + 日誌入門
斷言 在Java語言中,給出了3種處理系統錯誤的機制: 丟擲一個異常 日誌 使用斷言 那我們應該在什麼情況下去使用斷言呢? 斷言失敗是致命的,不可恢復的錯誤 斷言失敗只用於開發和測試階段。
Java開發筆記(三十二)字符型與整型相互轉化
傳播 out 字母 href 不但 java 個數 進制數 com 前面提到字符類型是一種新的變量類型,然而編碼實踐的過程中卻發現,某個具體的字符值居然可以賦值給整型變量!就像下面的例子代碼那樣,把字符值賦給整型變量,編譯器不但沒報錯,而且還能正常運行! // 字符允許
Java開發筆記(三十二)字元型與整型相互轉化
前面提到字元型別是一種新的變數型別,然而編碼實踐的過程中卻發現,某個具體的字元值居然可以賦值給整型變數!就像下面的例子程式碼那樣,把字元值賦給整型變數,編譯器不但沒報錯,而且還能正常執行! // 字元允許直接賦值給整型變數 private static void charToInt() { i
Java基礎(三十二)
內部類 背景: 雖然在類中的基本組成就是成員屬性與方法,但是在任何的語言裡面結構也是允許進行巢狀的,所以在一個類的內部都可以定義其他的類,這樣的類就稱為內部類。 1:什麼是內部類 內部類是一個獨立且完善的類結構,在一個類的內部除了屬性和方法之外可以繼續使用cla
【鏈塊技術50期】區塊鏈技術基礎語言(三十二):Go語言網路程式設計(下)
原文連結:區塊鏈技術基礎語言(三十二):Go語言網路程式設計(下) 本文緊接上文所述,講解socket程式設計和HTTP程式設計。 一、socket程式設計 在上一節我們介紹了網路體系的五層模型,介紹了每層模型所遵守的協議。TCP/IP是一個協議族,它由網路層的IP協議
聊聊高並發(三十二)實現一個基於鏈表的無鎖Set集合
target 方向 刪除 元素 min 集合 date 變量 find Set表示一種沒有反復元素的集合類,在JDK裏面有HashSet的實現,底層是基於HashMap來實現的。這裏實現一個簡化版本號的Set,有下面約束: 1. 基於鏈表實現。鏈表節點依照對象的h
(三十二)訂單管理-查詢訂單詳情
pos 查詢 oid item res ima 不用 close pro 查詢訂單詳情 點擊每一個訂單後面的訂單詳情,將該訂單的oid通過ajax傳遞到後臺查詢 步驟分析: 給按鈕添加事件 /store/WebCon
Linux學習(三十二)screen
oot mst tail pre linux article col install vmstat screen概述 我們可以將screen看成一個子窗口,我們可以通過命令將這個子窗口放入後臺運行而不關閉它。當我們有需要時,我們還可以將它調出來。 screen使用 安裝
企業分布式微服務雲SpringCloud SpringBoot mybatis (三十二)spring boot做調度任務
tro 一次 tis com href 什麽 init boot 2.6 構建工程 創建一個Springboot工程,在它的程序入口加上@EnableScheduling,開啟調度任務。 @SpringBootApplication @EnableScheduling p
Linux學習筆記(三十二)iptables filter表案例、 iptables nat表應用
iptables filter表案例、 iptables nat表應用 一、iptables filter表案例需求:將80、20、21端口放行,對22端口指定特定的ip才放行以下為操作方法:vim /usr/local/sbin/iptables.sh //加入如下內容#! /bin/bas
Jmeter(三十二)Jmeter Question 之 亂碼解讀
直接 默認 進行 json 字符 blog 文件中 內容 錄制完成 眾所周知,編碼的問題影響著眾多開發者,當然見多不怪。 先扒了一個編碼的原因,也就是為什麽要編碼: 計算機中存儲信息的最小單元是一個字節即 8 個 bit,所以能表示的字符範圍是 0~255 個 人
Linux學習總結(三十二)lamp之php安裝
php libphp5.so lamp PHP官網www.php.net當前主流版本為5.6/7.1 cd /usr/local/src/ wget http://cn2.php.net/distributions/php-5.6.30.tar.gz tar zxf php-5.6.30.tar
邏輯操作符的陷阱(三十二)
C++ 重載邏輯操作符 邏輯操作符陷阱 比較操作符 我們今天來看看邏輯操作符,它的原生語義是:操作數只有兩種值(true 和 false),邏輯表達式不用完全計算就能確定最終值,其最終結果只能是 true 或者 false。 下來我們來看個編程實驗#include