抽象工廠設計模式
Ⅰ JAVA設計模式,工廠方法和抽象工廠為什麼一個是類的創建模式,一個是對象的創建模式
工廠的方法是 工廠 的總類 就是 所有的生產東西的東西都是工廠類的
抽象工廠 具體的描述一個工廠 具體就是他是生產什麼 的 想汽車廠 和 飲料廠的區別 他門都可以叫工廠 所以他們是工廠的 一個實俐 汽車廠和 飲料廠 都屬於工廠類
Ⅱ 設計模式(二):簡單工廠,工廠和抽象工廠的區別
首先來看看這兩者的定義區別:工廠模式:定義一個用於創建對象的借口,讓內子類決定實例化容哪一個類抽象工廠模式:為創建一組相關或相互依賴的對象提供一個介面,而且無需指定他們的具體類個人覺得這個區別在於產品,如果產品單一,最合適用工廠模式,但是如果有多個業務品種、業務分類時,通過抽象工廠模式產生需要的對象是一種非常好的解決方式。再通俗深化理解下:工廠模式針對的是一個產品等級結構 ,抽象工廠模式針對的是面向多個產品等級結構的。再來看看工廠方法模式與抽象工廠模式對比:
Ⅲ 為什麼要用抽象工廠設計模式
隨便找本設計模式的書, 上面都會有講到的吧. 不過如果沒有一定的代碼經驗和積累, 就算看了可能也很難懂. 建議先理解工廠方法模式
Ⅳ 設計模式的設計原則
為什麼要提倡「Design Pattern呢?根本原因是為了代碼復用,增加可維護性。那麼怎麼才能實現代碼復用呢?面向對象有幾個原則:單一職責原則 (Single Responsiblity Principle SRP)開閉原則(Open Closed Principle,OCP)、里氏代換原則(Liskov Substitution Principle,LSP)、依賴倒轉原則(Dependency Inversion Principle,DIP)、介面隔離原則(Interface Segregation Principle,ISP)、合成/聚合復用原則(Composite/Aggregate Reuse Principle,CARP)、最小知識原則(Principle of Least Knowledge,PLK,也叫迪米特法則)。開閉原則具有理想主義的色彩,它是面向對象設計的終極目標。其他幾條,則可以看做是開閉原則的實現方法。
設計模式就是實現了這些原則,從而達到了代碼復用、增加可維護性的目的。 此原則是由Bertrand Meyer提出的。原文是:「Software entities should be open for extension,but closed for modification」。就是說模塊應對擴展開放,而對修改關閉。模塊應盡量在不修改原(是「原」,指原來的代碼)代碼的情況下進行擴展。那麼怎麼擴展呢?我們看工廠模式「factory pattern」:假設中關村有一個賣盜版盤和毛片的小子,我們給他設計一「光碟銷售管理軟體」。我們應該先設計一「光碟」介面。如圖:
[pre]
______________
|<>|
| 光碟 |
|_____________|
|+賣() |
| |
|_____________|
[/pre]
而盜版盤和毛片是其子類。小子通過「DiscFactory」來管理這些光碟。代碼為: publicclassDiscFactory{publicstatic光碟getDisc(Stringname){return(光碟)Class.forName(name).newInstance();}}有人要買盜版盤,怎麼實現呢? publicclass小子{publicstaticvoidmain(String[]args){光碟d=DiscFactory.getDisc(盜版盤);d.賣();}}如果有一天,這小子良心發現了,開始賣正版軟體。沒關系,我們只要再創建一個「光碟」的子類「正版軟體」就可以了,不需要修改原結構和代碼。怎麼樣?對擴展開放,對修改關閉——「開閉原則」。
工廠模式是對具體產品進行擴展,有的項目可能需要更多的擴展性,要對這個「工廠」也進行擴展,那就成了「抽象工廠模式」。 合成/聚合復用原則(Composite/Aggregate Reuse Principle,CARP)經常又叫做合成復用原則。合成/聚合復用原則就是在一個新的對象裡面使用一些已有的對象,使之成為新對象的一部分;新的對象通過向這些對象的委派達到復用已有功能的目的。它的設計原則是:要盡量使用合成/聚合,盡量不要使用繼承。
就是說要少用繼承,多用合成關系來實現。我曾經這樣寫過程序:有幾個類要與資料庫打交道,就寫了一個資料庫操作的類,然後別的跟資料庫打交道的類都繼承這個。結果後來,我修改了資料庫操作類的一個方法,各個類都需要改動。「牽一發而動全身」!面向對象是要把波動限制在盡量小的范圍。
在Java中,應盡量針對Interface編程,而非實現類。這樣,更換子類不會影響調用它方法的代碼。要讓各個類盡可能少的跟別人聯系,「不要與陌生人說話」。這樣,城門失火,才不至於殃及池魚。擴展性和維護性才能提高。 設計模式分為三種類型,共23種。 創建型模式:單例模式、抽象工廠模式、建造者模式、工廠模式、原型模式。 結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。 行為型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式(Interpreter模式)、狀態模式、策略模式、職責鏈模式(責任鏈模式)、訪問者模式。 按字典序排列簡介如下。
Abstract Factory(抽象工廠模式):提供一個創建一系列相關或相互依賴對象的介面,而無需指定它們具體的類。
Adapter(適配器模式):將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不兼容而不能一起工作的那些類可以一起工作。
Bridge(橋接模式):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
Builder(建造者模式):將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
Chain of Responsibility(責任鏈模式):為解除請求的發送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它。
Command(命令模式):將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作。
Composite(組合模式):將對象組合成樹形結構以表示「部分-整體」的層次結構。它使得客戶對單個對象和復合對象的使用具有一致性。
Decorator(裝飾模式):動態地給一個對象添加一些額外的職責。就擴展功能而言, 它比生成子類方式更為靈活。
Facade(外觀模式):為子系統中的一組介面提供一個一致的界面,Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
Factory Method(工廠模式):定義一個用於創建對象的介面,讓子類決定將哪一個類實例化。Factory Method使一個類的實例化延遲到其子類。
Flyweight(享元模式):運用共享技術有效地支持大量細粒度的對象。
Interpreter(解析器模式):給定一個語言, 定義它的文法的一種表示,並定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。
Iterator(迭代器模式):提供一種方法順序訪問一個聚合對象中各個元素,而又不需暴露該對象的內部表示。
Mediator(中介模式):用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
Memento(備忘錄模式):在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。
Observer(觀察者模式):定義對象間的一種一對多的依賴關系,以便當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動刷新。
Prototype(原型模式):用原型實例指定創建對象的種類,並且通過拷貝這個原型來創建新的對象。
Proxy(代理模式):為其他對象提供一個代理以控制對這個對象的訪問。
Singleton(單例模式):保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。 單例模式是最簡單的設計模式之一,但是對於Java的開發者來說,它卻有很多缺陷。在九月的專欄中,David Geary探討了單例模式以及在面對多線程(multi-threading)、類裝載器(class loaders)和序列化(serialization)時如何處理這些缺陷。
State(狀態模式):允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它所屬的類。
Strategy(策略模式):定義一系列的演算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得演算法的變化可獨立於使用它的客戶。
Template Method(模板方法模式):定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。
Visitor(訪問者模式):表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
從下一節開始,詳細描述以下每一種設計模式。 意圖
定義一個用於創建對象的介面,讓子類決定實例化哪一個類。Factory Method 使一個類的實例化延遲到其子類。
適用性 當一個類不知道它所必須創建的對象的類的時候。 當一個類希望由它的子類來指定它所創建的對象的時候。 當類將創建對象的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一信息局部化的時候。 意圖
提供一個創建一系列相關或相互依賴對象的介面,而無需指定它們具體的類。
適用性 一個系統要獨立於它的產品的創建、組合和表示時。 一個系統要由多個產品系列中的一個來配置時。 當你要強調一系列相關的產品對象的設計以便進行聯合使用時。 當你提供一個產品類庫,而只想顯示它們的介面而不是實現時。 意圖
將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
適用性 當創建復雜對象的演算法應該獨立於該對象的組成部分以及它們的裝配方式時。 當構造過程必須允許被構造的對象有不同的表示時。 意圖
用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。
適用性 當要實例化的類是在運行時刻指定時,例如,通過動態裝載;或者 為了避免創建一個與產品類層次平行的工廠類層次時;或者 當一個類的實例只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工實例化該類更方便一些。 意圖
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
適用性 當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時。 當這個唯一實例應該是通過子類化可擴展的,並且客戶應該無需更改代碼就能使用一個擴展的實例時。 意圖
將一個類的介面轉換成另外一個客戶希望的介面。Adapter 模式使得原本由於介面不兼容而不能一起工作的那些類可以一起工作。
適用性 你想使用一個已經存在的類,而它的介面不符合你的需求。 你想創建一個可以復用的類,該類可以與其他不相關的類或不可預見的類(即那些介面可能不一定兼容的類)協同工作。 (僅適用於對象Adapter)你想使用一些已經存在的子類,但是不可能對每一個都進行子類化以匹配它們的介面。對象適配器可以適配它的父類介面。 意圖
將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
適用性 你不希望在抽象和它的實現部分之間有一個固定的綁定關系。例如這種情況可能是因為,在程序運行時刻實現部分應可以被選擇或者切換。 類的抽象以及它的實現都應該可以通過生成子類的方法加以擴充。這時B r i d g e 模式使你可以對不同的抽象介面和實現部分進行組合,並分別對它們進行擴充。 對一個抽象的實現部分的修改應對客戶不產生影響,即客戶的代碼不必重新編譯。 (C++)你想對客戶完全隱藏抽象的實現部分。在C++中,類的表示在類介面中是可見的。 有許多類要生成。這樣一種類層次結構說明你必須將一個對象分解成兩個部分。Rumbaugh稱這種類層次結構為「嵌套的普化」(nested generalizations )。 你想在多個對象間共享實現(可能使用引用計數),但同時要求客戶並不知道這一點。一個簡單的例子便是Coplien的String類,在這個類中多個對象可以共享同一個字元串表示(StringRep)。 意圖
將對象組合成樹形結構以表示「部分-整體」的層次結構。C o m p o s i t e 使得用戶對單個對象和組合對象的使用具有一致性。
適用性 你想表示對象的部分—整體層次結構。 你希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。 意圖
動態地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。
適用性 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。 處理那些可以撤消的職責。 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。 意圖
為子系統中的一組介面提供一個一致的界面,Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
適用性 當你要為一個復雜子系統提供一個簡單介面時。子系統往往因為不斷演化而變得越來越復雜。大多數模式使用時都會產生更多更小的類。這使得子系統更具可重用性,也更容易對子系統進行定製,但這也給那些不需要定製子系統的用戶帶來一些使用上的困難。Facade可以提供一個簡單的預設視圖,這一視圖對大多數用戶來說已經足夠,而那些需要更多的可定製性的用戶可以越過Facade層。 客戶程序與抽象類的實現部分之間存在著很大的依賴性。引入Facade將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。 當你需要構建一個層次結構的子系統時,使用門面模式定義子系統中每層的入口點。如果子系統之間是相互依賴的,你可以讓它們僅通過Facade進行通訊,從而簡化了它們之間的依賴關系。 意圖
運用共享技術有效地支持大量細粒度的對象。
適用性 一個應用程序使用了大量的對象。 完全由於使用大量的對象,造成很大的存儲開銷。 對象的大多數狀態都可變為外部狀態。 如果刪除對象的外部狀態,那麼可以用相對較少的共享對象取代很多組對象。 應用程序不依賴於對象標識。由於Flyweight對象可以被共享,對於概念上明顯有別的對象,標識測試將返回真值。 意圖
為其他對象提供一種代理以控制對這個對象的訪問。
適用性
在需要用比較通用和復雜的對象指針代替簡單的指針的時候,使用Proxy模式。下面是一 些可以使用Proxy模式常見情況: 遠程代理(Remote Proxy)為一個對象在不同的地址空間提供局部代表。 虛代理(Virtual Proxy)根據需要創建開銷很大的對象。 保護代理(Protection Proxy)控制對原始對象的訪問。保護代理用於對象應該有不同 的訪問許可權的時候。 智能指引(Smart Reference)取代了簡單的指針,它在訪問對象時執行一些附加操作。 它的典型用途包括: 對指向實際對象的引用計數,這樣當該對象沒有引用時,可以自動釋放它(也稱為SmartPointers)。 當第一次引用一個持久對象時,將它裝入內存。 在訪問一個實際對象前,檢查是否已經鎖定了它,以確保其他對象不能改變它。 意圖
使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
適用性 有多個的對象可以處理一個請求,哪個對象處理該請求運行時刻自動確定。 你想在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。 可處理一個請求的對象集合應被動態指定。 意圖
將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作
適用性 像上面討論的MenuItem對象那樣,抽象出待執行的動作以參數化某對象。你可用過程語言中的回調(callback)函數表達這種參數化機制。所謂回調函數是指函數先在某處注冊,而它將在稍後某個需要的時候被調用。Command模式是回調機制的一個面向對象的替代品。 在不同的時刻指定、排列和執行請求。一個Command對象可以有一個與初始請求無關的生存期。如果一個請求的接收者可用一種與地址空間無關的方式表達,那麼就可將負責該請求的命令對象傳送給另一個不同的進程並在那兒實現該請求。 支持取消操作。Command的Execute操作可在實施操作前將狀態存儲起來,在取消操作時這個狀態用來消除該操作的影響。Command介面必須添加一個Execute操作,該操作取消上一次Execute調用的效果。執行的命令被存儲在一個歷史列表中。可通過向後和向前遍歷這一列表並分別調用Unexecute和Execute來實現重數不限的「取消」和「重做」。 支持修改日誌,這樣當系統崩潰時,這些修改可以被重做一遍。在Command介面中添加裝載操作和存儲操作,可以用來保持變動的一個一致的修改日誌。從崩潰中恢復的過程包括從磁碟中重新讀入記錄下來的命令並用Execute操作重新執行它們。 用構建在原語操作上的高層操作構造一個系統。這樣一種結構在支持事務(Transaction)的信息系統中很常見。一個事務封裝了對數據的一組變動。Command模式提供了對事務進行建模的方法。Command有一個公共的介面,使得你可以用同一種方式調用所有的事務。同時使用該模式也易於添加新事務以擴展系統。 意圖
給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
適用性 當有一個語言需要解釋執行, 並且你可將該語言中的句子表示為一個抽象語法樹時,可使用解釋器模式。而當存在以下情況時該模式效果最好: 該文法簡單對於復雜的文法, 文法的類層次變得龐大而無法管理。此時語法分析程序生成器這樣的工具是更好的選擇。它們無需構建抽象語法樹即可解釋表達式, 這樣可以節省空間而且還可能節省時間。 效率不是一個關鍵問題最高效的解釋器通常不是通過直接解釋語法分析樹實現的, 而是首先將它們轉換成另一種形式。例如,正則表達式通常被轉換成狀態機。但即使在這種情況下, 轉換器仍可用解釋器模式實現, 該模式仍是有用的。 意圖
提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。
適用性 訪問一個聚合對象的內容而無需暴露它的內部表示。 支持對聚合對象的多種遍歷。 為遍歷不同的聚合結構提供一個統一的介面(即, 支持多態迭代)。 意圖
用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
適用性 一組對象以定義良好但是復雜的方式進行通信。產生的相互依賴關系結構混亂且難以理解。 一個對象引用其他很多對象並且直接與這些對象通信,導致難以復用該對象。 想定製一個分布在多個類中的行為,而又不想生成太多的子類。 意圖
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。
適用性 必須保存一個對象在某一個時刻的(部分)狀態, 這樣以後需要時它才能恢復到先前的狀態。 如果一個用介面來讓其它對象直接得到這些狀態,將會暴露對象的實現細節並破壞對象的封裝性。 意圖
定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時, 所有依賴於它的對象都得到通知並被自動更新。
適用性 當一個抽象模型有兩個方面, 其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和復用。 當對一個對象的改變需要同時改變其它對象, 而不知道具體有多少對象有待改變。 當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之,你不希望這些對象是緊密耦合的。 意圖
允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它的類。
適用性 一個對象的行為取決於它的狀態, 並且它必須在運行時刻根據狀態改變它的行為。 一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。通常, 有多個操作包含這一相同的條件結構。State模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作為一個對象,這一對象可以不依賴於其他對象而獨立變化。 意圖
定義一系列的演算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得演算法可獨立於使用它的客戶而變化。
適用性 許多相關的類僅僅是行為有異。「策略」提供了一種用多個行為中的一個行為來配置一個類的方法。 需要使用一個演算法的不同變體。例如,你可能會定義一些反映不同的空間/時間權衡的演算法。當這些變體實現為一個演算法的類層次時,可以使用策略模式。 演算法使用客戶不應該知道的數據。可使用策略模式以避免暴露復雜的、與演算法相關的數據結構。 一個類定義了多種行為, 並且這些行為在這個類的操作中以多個條件語句的形式出現。將相關的條件分支移入它們各自的Strategy類中以代替這些條件語句。 意圖
定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。Te m p l a t e M e t h o d 使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。
適用性 一次性實現一個演算法的不變的部分,並將可變的行為留給子類來實現。 各子類中公共的行為應被提取出來並集中到一個公共父類中以避免代碼重復。這是Opdyke和Johnson所描述過的「重分解以一般化」的一個很好的例子。首先識別現有代碼中的不同之處,並且將不同之處分離為新的操作。最後,用一個調用這些新的操作的模板方法來替換這些不同的代碼。 控制子類擴展。模板方法只在特定點調用「hook」操作,這樣就只允許在這些點進行擴展。 意圖
表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
適用性 一個對象結構包含很多類對象,它們有不同的介面,而你想對這些對象實施一些依賴於其具體類的操作。 需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作「污染」這些對象的類。Visitor使得你可以將相關的操作集中起來定義在一個類中。當該對象結構被很多應用共享時,用Visitor模式讓每個應用僅包含需要用到的操作。 定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者的介面,這可能需要很大的代價。如果對象結構類經常改變,那麼可能還是在這些類中定義這些操作較好。
Ⅳ JAVA設計模式中,抽象工廠與工廠方法的區別是什麼,兩者有什麼不同嗎
抽象工廠的方法經常以工廠方法的方式實現,兩者很容易混淆。他們的工作都是負內責創建對象。容不同的是工廠方法用的方法是繼承過來的,而抽象工廠是通過對象組合。其實整個工廠方法模式,只不過就是通過子類來創建對象。只需知道超類型就可以了,具體的類型由子類負責。在這一點上,抽象工廠表示毫無壓力,但是做法不同。抽象工廠提供一個用來創建一個產品家族的抽象類型,這個類型的子類定義了產品被產生的方法。要想使用這個工廠,必須先實例化它(產品家族的抽象類型,通過組合而來)。它的優點是可以把一群相關的產品集合起來,缺點是如果有新產品加入需要修改介面代碼,這會涉及到所有子類介面的更改,是一個很繁瑣的工作。而工廠方法有點相反,它只是創建一個產品,不需要很大的介面,一個方法就可以了。如果你目前還不知道將來需要實例化哪些類時,也可以使用工廠方法,只要繼承它,實現工廠方法就可以了。
舉一個例子:如果你有一個超市,只買一種物品,建議用工廠方法。如果有很多物品,就使用抽象工廠。當然,各有各的特點,最終都是學以致用,解決實際問題。很多問題都是結合各種辦法解決的。
Ⅵ java 設計模式(工廠方法)
面向抽象(抽象類或介面)編程。
IWorkFactory studentWorkFactory = new StudentWorkFactory(); 注意:類型是介面類型,即抽象工廠,抽象工廠生產的是抽象產品,而new的則是具體工廠,是由子類實現的,具體工廠生產具體產品。面向抽象的好處:1.在設計抽象的時候不用管具體的實現,只要定義介面知道它用來干什麼就行,這樣,我只需要知道抽象介面就能繼續下面的開發設計工作了,而不用事先設計具體的實現內容;2. 可以擴展多個子類實現抽象介面,更利於系統後期的擴展,而對原系統不造成任何影響,即:開-閉原則。
TeacherWork tt = new TeacherWork(); 不用說就是面向具體實現類編程,缺點就是擴展性不好,對系統後期維護擴展影響較大。
舉個簡單的例子:
假如在系統的A.java中代碼中使用了TeacherWork 類型對象,是滿足了目前軟體的需求,但是,如果有一天需求變化了需要一個StudentWork 類型對象,該怎麼辦?只能修改A.java類來滿足這樣的修改需求。這樣就影響了原來系統結構穩定性,需要重新調試和測試,而這帶來的維護成本是非常大的,有時可能還會帶來系統錯誤,而影響系統運行。
如果在A.java類中應用Work介面類型就不會存在這種問題,A.java不需要任何修改,只需要修改注入到A中的Work介面的具體實現類即可。
面向抽象編程的好處就在於對系統維護和擴展上,即在不影響原系統穩定運行的基礎上增加新的擴展行為,即要符合「開-閉」原則。可能會因此而失去一定的效率問題,但是對於後期的維護成本來說,這個可以忽略不計。 推薦你一本好書:《軟體秘笈-設計模式那點事》其中講解的設計模式很到位,還有每個模式的靜態類圖和JDK中設計模式的具體分析講解,讀了收獲一定很大。祝你成功!
Ⅶ 軟體設計模式有哪些
設計模式列表基礎模式
委託模式
介面模式
代理模式
創建型模式
抽象工廠模式 (Abstract Factory) ,提供一個創建一系列相關或相互依賴對象的介面,而無需指定它們具體的類。
生成器模式 (Builder),將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
工廠方法模式 (Factory Methord) ,定義一個用於創建對象的介面,讓子類決定將哪一個類實例化。Factory Method使一個類的實例化延遲到其子類。
原型模式 (Prototype) ,用原型實例指定創建對象的種類,並且通過拷貝這個原型來創建新的對象。
單例模式 (Singleton),保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
結構型模式
適配器模式 (Adapter) ,將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不兼容而不能一起工作的那些類可以一起工作。
橋接模式 (Bridge) ,將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
組合模式 (Composite) ,將對象組合成樹形結構以表示「部分-整體」的層次結構。它使得客戶對單個對象和復合對象的使用具有一致性。
容器模式
修飾模式 (Decorator) ,動態地給一個對象添加一些額外的職責。就擴展功能而言, 它比生成子類方式更為靈活。
擴展性模式
外觀模式
享元模式
管道與過濾器模式
代理模式 (Proxy) ,為其他對象提供一個代理以控制對這個對象的訪問。
行為模式
責任鏈模式 (Chain of Responsibility) ,為解除請求的發送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它。
命令模式 (Command) ,將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作。
柯里化模式
事件監聽器模式
解釋器模式
迭代器模式
中介者模式
備忘錄模式 (Memento) ,在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。
觀察者模式 (Observer) ,定義對象間的一種一對多的依賴關系,以便當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動刷新。
狀態模式 (State) ,允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它所屬的類。
策略模式 (Strategy) ,定義一系列的演算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得演算法的變化可獨立於使用它的客戶。
模板方法模式
訪問者模式 (Visitor),表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
層次訪問者模式
並發模式
模式 Action at a distance
模式 Balking
模式 Guarded suspension
模式 Scheler
模式 Read write lock
模式 Double checked locking
模式 Disable job requests while running job
實時模式
模式 Scheled task
模式 User interface
模式 Disable job requests while running job
其他
模型—視圖—控制器模式
Ⅷ java 抽象工廠模式
工廠模式在項目中是常常用到的,有人說只有大項目才會用到,小項目是體會不出來.其實使用設計模式與項目的大小沒有實質性的聯系.設計模式是經驗的總結而不是衡量項目大小的標准.
以開發項目的DAO層為例,在項目中客戶的需求是常常變動的,臨時更換資料庫的需求也是常常發生的,那我們要如何解決跨資料庫的功能,這里就要使用到抽象工廠模式了.工廠模式常常用於創建多系列化的對象(如Orale系列,MySql系列)
1.首先定義相關介面(與平常的做法沒什麼區別)
Java代碼
// 角色表DAO介面
interface IroleDao {
void insert();
void update();
}
// 用戶表DAO介面
interface IuserDao {
void find();
void delete();
}
// 角色表DAO介面
interface IroleDao {
void insert();
void update();
}
// 用戶表DAO介面
interface IuserDao {
void find();
void delete();
} 2.不同的資料庫有不同的SQL語句所以實現時必須分資料庫來實現
Java代碼
// 用戶表Oralce資料庫DAO
class OracleuserDao implements IuserDao {
public void delete() {
System.out.println("Oralce 刪除用戶表數據");
}
public void find() {
System.out.println("Oralce 查詢用戶表數據");
}
}
// 用戶表MySql資料庫DAO
class MySqluserDao implements IuserDao {
public void delete() {
System.out.println("MySql 刪除用戶數據");
}
public void find() {
System.out.println("MySql 查詢用戶數據");
}
}
// 角色表Oracle資料庫DAO
class OracleroleDao implements IroleDao {
public void insert() {
System.out.println("Oralce 對角色表插入數據");
}
public void update() {
System.out.println("Oracle 對角色表更新數據");
}
}
// 角色表MySql資料庫DAO
class MySqlroleDAO implements IroleDao {
public void insert() {
System.out.println("MySql 對角色表插入數據");
}
public void update() {
System.out.println("Mysql 對角色表更新數據");
}
}
// 用戶表Oralce資料庫DAO
class OracleuserDao implements IuserDao {
public void delete() {
System.out.println("Oralce 刪除用戶表數據");
}
public void find() {
System.out.println("Oralce 查詢用戶表數據");
}
}
// 用戶表MySql資料庫DAO
class MySqluserDao implements IuserDao {
public void delete() {
System.out.println("MySql 刪除用戶數據");
}
public void find() {
System.out.println("MySql 查詢用戶數據");
}
}
// 角色表Oracle資料庫DAO
class OracleroleDao implements IroleDao {
public void insert() {
System.out.println("Oralce 對角色表插入數據");
}
public void update() {
System.out.println("Oracle 對角色表更新數據");
}
}
// 角色表MySql資料庫DAO
class MySqlroleDAO implements IroleDao {
public void insert() {
System.out.println("MySql 對角色表插入數據");
}
public void update() {
System.out.println("Mysql 對角色表更新數據");
}
}
這里增加了一套DAO的實現 (與平時有所不同,如果有10個資料庫就要加上10種不同的實現,比較麻煩呀)
3.定義DAO工廠介面與實現(利用java反射機制生產出你需要的DAO如:userDAO,roleDao)
Java代碼
// DAO工廠
abstract class DaoFactory {
public static DaoFactory getInstance(String classname) {
DaoFactory = null;
try {
= (DaoFactory) Class.forName(classname).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return ;
}
abstract IuserDao getuser();
abstract IroleDao getrole();
}
// Oralce工廠
class OracleFactory extends DaoFactory {
public IroleDao getrole() {
return new OracleroleDao();
}
public IuserDao getuser() {
return new OracleuserDao();
}
}
// MySql工廠
class MysqlFactory extends DaoFactory {
public IroleDao getrole() {
return new MySqlroleDAO();
}
public IuserDao getuser() {
return new MySqluserDao();
}
}
// DAO工廠
abstract class DaoFactory {
public static DaoFactory getInstance(String classname) {
DaoFactory = null;
try {
= (DaoFactory) Class.forName(classname).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return ;
}
abstract IuserDao getuser();
abstract IroleDao getrole();
}
// Oralce工廠
class OracleFactory extends DaoFactory {
public IroleDao getrole() {
return new OracleroleDao();
}
public IuserDao getuser() {
return new OracleuserDao();
}
}
// MySql工廠
class MysqlFactory extends DaoFactory {
public IroleDao getrole() {
return new MySqlroleDAO();
}
public IuserDao getuser() {
return new MySqluserDao();
}
}
4. 定義配置文件
Java代碼
class Config {
// Oralce
static final String ORALCE = "org.abc.OracleFactory";
static final String MYSQL = "org.abc.MysqlFactory";
}
class Config {
// Oralce
static final String ORALCE = "org.abc.OracleFactory";
static final String MYSQL = "org.abc.MysqlFactory";
}
配置文件可以定義到XML中去(好處:修改配置項之後不需要對JAVA文件進行編譯.)
5.測試你的輸出的DAO
Java代碼
public class Dao {
public static void main(String[] args) {
DaoFactory.getInstance(Config.ORALCE).getrole().insert();
DaoFactory.getInstance(Config.MYSQL).getrole().insert();
}
}
public class Dao {
public static void main(String[] args) {
DaoFactory.getInstance(Config.ORALCE).getrole().insert();
DaoFactory.getInstance(Config.MYSQL).getrole().insert();
}
}
總結
使用條件:一系列介面有一系列的實現
如上IuserDao、IroleDao等一系列的介面,他們可以有一系列的實現(Oracle方式、MySql方式)
OracleuserDao、OracleroleDao、MySqluserDao、MySqlroleDAO
組成元素(以上面例子)
一系列介面:IuserDao、IroleDao
一系列實現:Oracle系列、MySql系列
系列工廠類:Oracle系列工廠類、MySql系列工廠類(必須繼承抽象工廠類)
抽象工廠類:DaoFactory
Ⅸ 什麼是設計模式
java中的設計模式:
總體來說設計模式分為三大類:
創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
Ⅹ 設計模式都有哪些
總體來說設計模式分為三大類:
一、創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
二、結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
三、行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
1、工廠方法模式:
定義一個用於創建對象的介面,讓子類決定實例化哪一個類。Factory Method 使一個類的實例化延遲到其子類。
工廠模式有一個問題就是,類的創建依賴工廠類,也就是說,如果想要拓展程序,必須對工廠類進行修改,這違背了閉包原則,所以,從設計角度考慮,有一定的問題,這就用到工廠方法模式。
創建一個工廠介面和創建多個工廠實現類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的代碼。
2、抽象工廠模式:
提供一個創建一系列相關或相互依賴對象的介面,而無需指定它們具體的類。抽象工廠需要創建一些列產品,著重點在於"創建哪些"產品上,也就是說,如果你開發,你的主要任務是劃分不同差異的產品線,並且盡量保持每條產品線介面一致,從而可以從同一個抽象工廠繼承。
3、單例模式:
單例對象(Singleton)是一種常用的設計模式。在Java應用中,單例對象能保證在一個JVM中,該對象只有一個實例存在。這樣的模式有幾個好處:
(1)某些類創建比較頻繁,對於一些大型的對象,這是一筆很大的系統開銷。
(2)省去了new操作符,降低了系統內存的使用頻率,減輕GC壓力。
(3)有些類如交易所的核心交易引擎,控制著交易流程,如果該類可以創建多個的話,系統完全亂了。(比如一個軍隊出現了多個司令員同時指揮,肯定會亂成一團),所以只有使用單例模式,才能保證核心交易伺服器獨立控制整個流程。
4、建造者模式:
將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
5、原型模式:
原型模式雖然是創建型的模式,但是與工程模式沒有關系,從名字即可看出,該模式的思想就是將一個對象作為原型,對其進行復制、克隆,產生一個和原對象類似的新對象。本小結會通過對象的復制,進行講解。在Java中,復制對象是通過clone()實現的,先創建一個原型類。
6、適配器模式:
適配器模式將某個類的介面轉換成客戶端期望的另一個介面表示,目的是消除由於介面不匹配所造成的類的兼容性問題。主要分為三類:類的適配器模式、對象的適配器模式、介面的適配器模式。
7、裝飾器模式:
顧名思義,裝飾模式就是給一個對象增加一些新的功能,而且是動態的,要求裝飾對象和被裝飾對象實現同一個介面,裝飾對象持有被裝飾對象的實例。
8、代理模式:
代理模式就是多一個代理類出來,替原對象進行一些操作,比如我們在租房子的時候回去找中介,為什麼呢?因為你對該地區房屋的信息掌握的不夠全面,希望找一個更熟悉的人去幫你做,此處的代理就是這個意思。
9、外觀模式:
外觀模式是為了解決類與類之家的依賴關系的,像spring一樣,可以將類和類之間的關系配置到配置文件中,而外觀模式就是將他們的關系放在一個Facade類中,降低了類類之間的耦合度,該模式中沒有涉及到介面。
10、橋接模式:
橋接模式就是把事物和其具體實現分開,使他們可以各自獨立的變化。橋接的用意是:將抽象化與實現化解耦,使得二者可以獨立變化,像我們常用的JDBC橋DriverManager一樣。
JDBC進行連接資料庫的時候,在各個資料庫之間進行切換,基本不需要動太多的代碼,甚至絲毫不用動,原因就是JDBC提供統一介面,每個資料庫提供各自的實現,用一個叫做資料庫驅動的程序來橋接就行了。
11、組合模式:
組合模式有時又叫部分-整體模式在處理類似樹形結構的問題時比較方便。使用場景:將多個對象組合在一起進行操作,常用於表示樹形結構中,例如二叉樹,數等。
12、享元模式:
享元模式的主要目的是實現對象的共享,即共享池,當系統中對象多的時候可以減少內存的開銷,通常與工廠模式一起使用。
13、策略模式:
策略模式定義了一系列演算法,並將每個演算法封裝起來,使其可以相互替換,且演算法的變化不會影響到使用演算法的客戶。需要設計一個介面,為一系列實現類提供統一的方法,多個實現類實現該介面,設計一個抽象類(可有可無,屬於輔助類),提供輔助函數。
14、模板方法模式:
一個抽象類中,有一個主方法,再定義1...n個方法,可以是抽象的,也可以是實際的方法,定義一個類,繼承該抽象類,重寫抽象方法,通過調用抽象類,實現對子類的調用。
15、觀察者模式:
觀察者模式很好理解,類似於郵件訂閱和RSS訂閱,當我們瀏覽一些博客或wiki時,經常會看到RSS圖標,就這的意思是,當你訂閱了該文章,如果後續有更新,會及時通知你。
其實,簡單來講就一句話:當一個對象變化時,其它依賴該對象的對象都會收到通知,並且隨著變化!對象之間是一種一對多的關系。
16、迭代子模式:
顧名思義,迭代器模式就是順序訪問聚集中的對象,一般來說,集合中非常常見,如果對集合類比較熟悉的話,理解本模式會十分輕松。這句話包含兩層意思:一是需要遍歷的對象,即聚集對象,二是迭代器對象,用於對聚集對象進行遍歷訪問。
17、責任鏈模式:
責任鏈模式,有多個對象,每個對象持有對下一個對象的引用,這樣就會形成一條鏈,請求在這條鏈上傳遞,直到某一對象決定處理該請求。但是發出者並不清楚到底最終那個對象會處理該請求,所以,責任鏈模式可以實現,在隱瞞客戶端的情況下,對系統進行動態的調整。
18、命令模式:
命令模式的目的就是達到命令的發出者和執行者之間解耦,實現請求和執行分開。
19、備忘錄模式:
主要目的是保存一個對象的某個狀態,以便在適當的時候恢復對象,個人覺得叫備份模式更形象些,通俗的講下:假設有原始類A,A中有各種屬性,A可以決定需要備份的屬性,備忘錄類B是用來存儲A的一些內部狀態,類C呢,就是一個用來存儲備忘錄的,且只能存儲,不能修改等操作。
20、狀態模式:
狀態模式在日常開發中用的挺多的,尤其是做網站的時候,我們有時希望根據對象的某一屬性,區別開他們的一些功能,比如說簡單的許可權控制等。
21、訪問者模式:
訪問者模式把數據結構和作用於結構上的操作解耦合,使得操作集合可相對自由地演化。訪問者模式適用於數據結構相對穩定演算法又易變化的系統。因為訪問者模式使得演算法操作增加變得容易。
若系統數據結構對象易於變化,經常有新的數據對象增加進來,則不適合使用訪問者模式。訪問者模式的優點是增加操作很容易,因為增加操作意味著增加新的訪問者。訪問者模式將有關行為集中到一個訪問者對象中,其改變不影響系統數據結構。其缺點就是增加新的數據結構很困難。
22、中介者模式:
中介者模式也是用來降低類類之間的耦合的,因為如果類類之間有依賴關系的話,不利於功能的拓展和維護,因為只要修改一個對象,其它關聯的對象都得進行修改。
如果使用中介者模式,只需關心和Mediator類的關系,具體類類之間的關系及調度交給Mediator就行,這有點像spring容器的作用。
23、解釋器模式:
解釋器模式一般主要應用在OOP開發中的編譯器的開發中,所以適用面比較窄。
(10)抽象工廠設計模式擴展閱讀:
介紹三本關於設計模式的書:
1、《設計模式:可復用面向對象軟體的基礎》
作者:[美] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
出版社: 機械工業出版社
2、《軟體秘笈:設計模式那點事》
作者:鄭阿奇
出版社:電子工業出版社
3、《設計模式:基於C#的工程化實現及擴展》
作者:王翔
出版社:電子工業出版社