java设计模式学习
一、設計模式常用類型
- ?創建型模式:對象的創建與使用分離,不需要關注對象的創建細節,這樣可以降低系統的耦合度
- 結構型模式:或對象按某種布局組成更大的結構。它分為類結構型模式和對象結構型模式,前者采用繼承機制來組織接口和類,后者釆用組合或聚合來組合對象;由于組合關系或聚合關系比繼承關系耦合度低,滿足“合成復用原則”,所以對象結構型模式比類結構型模式具有更大的靈活性
- 行為模式:描述程序在運行時復雜的流程控制,即描述多個類或對象之間怎樣相互協作共同完成單個對象都無法單獨完成的任務,它涉及算法與對象間職責的分配;行為型模式分為類行為模式和對象行為模式,前者采用繼承機制來在類間分派行為,后者采用組合或聚合在對象間分配行為。由于組合關系或聚合關系比繼承關系耦合度低,滿足“合成復用原則”,所以對象行為模式比類行為模式具有更大的靈活性
Spring常用的設計模式:
- 工廠模式:只對結果負責,封裝創建過程
- BeanFactory(簡單工廠模式)
- 單例模式:保證獨一無二
- ApplicationContext,@Component
- 原型模式:可以復制千千萬萬
- PrototypeBean
- 代理模式:找人辦事,增強職責
- ProxyFactoryBean、JdkDynamicAopProxy、CglibAopProxy
- 委派模式:干活算你,功勞算我
- DispatcherServlet、BeanDefinitionParserDelegate
- 策略模式:用戶選擇,結果統一
- InstaniationStragegy
- 模版模式:流程標準化,自己實現定制
- JdbcTemplate、RestTemplate
- 適配器模式:兼容轉換頭
- AdvisorAdapter、HandlerAdapter
- 裝飾者模式:包裝,同宗同源
- InputStreamSource、EncodedResource、HttpHeadResponseDecorator
- 觀察者模式:在任務完成時通知
- ContextLoaderListener
二、工廠模式
- 簡單工廠模式
- 優點:面向對象編程思想,屏蔽代碼實現,工廠面向所有調用者
- 缺點:新增一個產品的話會對代碼進行重寫,不符合OCP開閉原則
? ? ? ? ? ?
- 工廠方法模式
- 優點:滿足里氏替換原則、迪米特法則、開閉原則;靈活型強,新產品只要新增一個工廠實現類就好
- 缺點:工廠實現類的個數隨著時間推移會增多,增加復雜度;只能生產一種產品(游戲類),此弊端可以用抽象工廠解決
????????????????
- ?抽象工廠模式
- 優點:一個產品族中的多個對象被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的對象(將一個系列的產品統一一起創建);
- 缺點:產品族擴展非常困難,要增加一個系列的某一產品,既要修改工廠抽象類里加代碼,又修改具體的實現類里面加代碼;增加了系統的抽象性和理解難度
- 適用于:定義好產品族系列產品不變,產品級別可變的情況
? ? ?
?三、單例模式
? ? ? ? 單例模式需要構造方法私有化,提供公共靜態方法獲取單例對象
- 餓漢模式
- 對象初始化時創建靜態私有的單一對象,初期就建好
- 賴漢模式
- 需要的時候再創建,原則上只new一次對象,多線程可能出現線程安全問題;可以通過同步法則規避此問題
- 靜態內部類構造對象,內部類中new一個需要的對象,外部類暴露調用接口(延遲加載,線程安全)
- 枚舉類型,保證實例唯一和線程安全
四、原型模式
? ? ? ??原型模式(Prototype Pattern)是用于創建重復的對象,同時又能保證性能。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式,類似可以參考java中淺拷貝和深拷貝(一般都是淺拷貝)
- 淺拷貝,拷貝的新對象中包含原有對象的基本類型和對象引用類型;特別注意Spring中BeanUtils.copyProperties()只會拷貝可讀可寫的屬性(含有set方法,反射機制讀(get)然后重寫(set)到新對象中),Cloneable接口clone()默認也是實現的淺拷貝(引用類型需要自己來實現new)
- 深拷貝,整個對象包括內容全部重新創建,最佳方式是利用序列化重新創建(實現Serializable);
- 利用ObjectMapper來json格式轉化(objectMapper.readValue(objectMapper.writeValueAsString(person), Man.class)),但對象包括所有屬性對象要實現Serializable并擁有默認構造和set/get方法(json字符串轉對象需要有無參構造和set/get方法)——太麻煩
- 利用java流來實現(ObjectOutputStream(byteArrayOutputStream).writeObject(object);ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())).readObject())——對象和對象屬性只需要實現Serializable,相對簡單,并且byteArrayOutputStream不用關閉流,close()方法也是空的,用完gc回收了
五、建造者模式
???????建造者(Builder)模式的主要角色如下:
? ? ? ??
? ? ? ? ?和工廠模式的區別:
- 建造者模式更加注重方法的調用順序,工廠模式注重創建對象。
- 創建對象的力度不同,建造者模式創建復雜的對象,由各種復雜的部件組成,工廠模式創建出來的對象都一樣
- 關注重點不一樣,工廠模式只需要把對象創建出來就可以了,而建造者模式不僅要創建出對象,還要知道對象由哪些部件組成。
- 建造者模式根據建造過程中的順序不一樣,最終對象部件組成也不一樣。
- 創建復雜對象,就可以考慮使用建造者模式
六、代理模式
- 靜態代理
????????由程序員創建代理類或特定工具自動生成源代碼再對其編譯,在程序運行前代理類的 .class 文件就已經存在了,同時目標類需要實現父接口
????????
?????????很明顯如果女人改變了,媒人也需要修改信息,違背了OCP開閉原則
- JDK動態代理
? ? ? ? 運行時在內存動態創建代理,利用jdk自帶的Proxy工具創建代理,并且實現InvocationHandler接口,而且目標類需要實現父接口或繼承父類
????????
- ?cglib動態代理
? ? ? ? 也是在運行時內存動態創建代理類或實現接口,目標類不用實現或繼承類,又叫子類代理,代理類是目標類的子類,比如springAop中的ObjenesisCglibAopProxy代理實現
????????
七、適配器模式
? ? ? ? 適配器
- 模式特點
- 適配器模式(Adapter)包含以下主要角色。
- 目標(Target)接口:當前系統業務所期待的接口,它可以是抽象類或接口。
- 適配者(Adaptee)類:它是被訪問和適配的現存組件庫中的組件接口。
- 適配器(Adapter)類:它是一個轉換器,通過繼承或引用適配者的對象,把適配者接口轉換成目標接口,讓客戶按目標接口的格式訪問適配者。
- 類適配:繼承適配者使自己成為適配者,不提倡
- ?組合適配:委派式調用,更靈活
八、橋接模式
????????橋接(Bridge)模式的定義如下:將抽象與實現分離,使它們可以獨立變化。它是用組合關系代替繼承關系來實現,從而降低了抽象和實現這兩個可變維度的耦合度。
? ? ? ? 橋接(Bridge)模式包含以下主要角色:
?九、裝飾者模式
????????裝飾器(Decorator)模式的定義:指在不改變現有對象結構的情況下,動態地給該對象增加一些職責(即增加其額外功能)的模式,它屬于對象結構型模式。
????????裝飾器模式主要包含以下角色:
? 十、外觀模式(門面模式)
?????????外觀(Facade)模式又叫作門面模式,是一種通過為多個復雜的子系統提供一個一致的接口,而使這些子系統更加容易被訪問的模式。該模式對外有一個統一接口,外部應用程序不用關心內部子系統的具體細節,這樣會大大降低應用程序的復雜度,提高了程序的可維護性。? ?
????????外觀(Facade)模式包含以下主要角色:
? 十一、亨元模式(后期代碼維護優化可以用到)
????????享元(Flyweight)模式的定義:運用共享技術來有效地支持大量細粒度對象的復用。它通過共享已經存在的對象來大幅度減少需要創建的對象數量、避免大量相似類的開銷,從而提高系統資源的利用率。
????????享元模式的定義提出了兩個要求,細粒度和共享對象。因為要求細粒度,所以不可避免地會使對象數量多且性質相近,此時我們就將這些對象的信息分為兩個部分:內部狀態和外部狀態。
- 內部狀態指對象共享出來的信息,存儲在享元信息內部,并且不會隨環境的改變而改變;
- 外部狀態指對象得以依賴的一個標記,隨環境的改變而改變,不可共享,可以動態注入。
享元模式的主要角色有如下:
- 抽象享元角色(Flyweight):是所有的具體享元類的基類,為具體享元規范需要實現的公共接口,非享元的外部狀態以參數的形式通過方法傳入。
- 具體享元(Concrete Flyweight)角色:實現抽象享元角色中所規定的接口。
- 非享元(Unsharable Flyweight)角色:是不可以共享的外部狀態,它以參數的形式注入具體享元的相關方法中。
- 享元工廠(Flyweight Factory)角色:負責創建和管理享元角色。當客戶對象請求一個享元對象時,享元工廠檢査系統中是否存在符合要求的享元對象,如果存在則提供給客戶;如果不存在的話,則創建一個新的享元對象。
備注:常見的-128~127的整型包裝類常量池(初始化就創建好)以及字符串常量池都是利用亨元模式,大大節省內存空間,物理上放在堆內存中,邏輯上放在方法區(jdk1.8后是元空間的實現)
?十二、組合模式
????????組合(Composite Pattern)模式的定義:有時又叫作整體-部分(Part-Whole)模式,它是一種將對象組合成樹狀的層次結構的模式,用來表示“整體-部分”的關系,使用戶對單個對象和組合對象具有一致的訪問性,屬于結構設計模式。
? ? ? ? 層層嵌套,類似與鏈表結構;整體-部分結構中部分數目不宜過多,特別是部分如果差別很大,使結構復雜,不易讀難維護;不容易使用繼承增加構建新方法。
?????????組合模式包含以下主要角色。
?十三、觀察者模式
????????當對象間存在一對多關系時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。
????????觀察者模式使用三個類 Subject、Observer 和 Client。Subject 對象帶有綁定觀察者到 Client 對象和從 Client 對象解綁觀察者的方法。我們創建?Subject?類、Observer?抽象類和擴展了抽象類?Observer?的實體類。
代碼大致這樣......
- 定義觀察目標對象Wallet
- 定義?觀察者抽象類PaymentObject
- 銀行擴展了觀察者?PaymentObject,設置PaymentBank觀察者實體類
- ?妻子擴展了觀察者?PaymentObject,設置PaymentWife觀察者實體類
- ?兒子擴展了觀察者?PaymentObject,設置PaymentChildren觀察者實體類
- ?建立服務,運行程序......
你錢包有一筆錢新入賬,可以還錢給工商銀行了吧!
你錢包有一筆錢新入賬,可以上交給老婆了吧!
你錢包有一筆錢新入賬,可以給兒子交學費了吧 !? ? ??
?備注:可以參考事件總線框架EventBus,利用觀察者模式做為消息隊列,只限于單個jvm中(單進程);JdbcTemplate中query方法用到了模板模式和觀察者模式,使用的是同步回調方式~~~
十四、策略模式?
????????在策略模式(Strategy Pattern)中,一個類的行為或其算法可以在運行時更改。這種類型的設計模式屬于行為型模式,在策略模式中,我們創建表示各種策略的對象和一個行為隨著策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行算法。
?策略模式的主要角色如下:
?十五、命令模式?
????????命令(Command)模式的定義如下:將一個請求封裝為一個對象,使發出請求的責任和執行請求的責任分割開。這樣兩者之間通過命令對象進行溝通,這樣方便將命令對象進行儲存、傳遞、調用、增加與管理
?命令模式包含以下主要角色:
??十六、迭代器模式?
????????迭代器模式(Iterator Pattern)用于順序訪問集合對象的元素,不需要知道集合對象的底層表示。每次都需要新增容器實現類和迭代器實現類
????????迭代器模式主要包含以下角色:
備注:借鑒Collection子集iterator()方法,由于正常集合在遍歷過程中改變集合結構(增刪),有可能導致不確定性異常,因為每次刪除新增都有可能讓集合元素重新排布,迭代器模式可以避免這種情況,實際上就是在原有集合上面包裝記錄有效位置一層,逃離了通過索引位置index的操作。
十七、職責鏈模式?
??????顧名思義,責任鏈模式(Chain of Responsibility Pattern)為請求創建了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發送者和接收者進行解耦。這種類型的設計模式屬于行為型模式。在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個對象不能處理該請求,那么它會把相同的請求傳給下一個接收者,依此類推。
使用場景:?
????????1、有多個對象可以處理同一個請求,具體哪個對象處理該請求由運行時刻自動確定。 2、在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。 3、可動態指定一組對象處理請求。
職責鏈模式主要包含以下角色:
? ? ? ? 備注:常用的兩種實現方式,用鏈表存儲處理器和用數組存儲處理器,常用的框架有Filter和Interceptor
- Filter:采用數組存儲filter,鏈路中采用遞歸調用方法doFilter(...,chain),所以過濾器中有過濾器鏈chain的說法,實際就是遞歸實現
- Interceptor:數據存儲攔截器,調用者通過正向循環執行preHandle(...)和逆向循環執行postHandle(...),以及渲染后的afterCompleting(...)調用
?十八、狀態模式?
? ? ? ? 狀態變化影響某一行為,比較雞肋
?十九、回調模式
? ? ? ?分為同步和異步回調,比模板模式更靈活,JdbcTemplate、RedisTemplate等都有應用
import lombok.Data; import org.springframework.util.Assert;import java.io.Serializable;@Data public class Person implements Serializable {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}public void setName(String name) {this.name = name;}public <T> T query(String choose, ResultSetExtractor<T> extract) {Assert.notNull(choose, "SQL must not be null");Assert.notNull(extract, "extract must not be null");class CallBackHand implements ICallBackHand<T> {public T doInState(String manJson) {System.out.println(choose + " 調用第三方執行了!");return extract.extractData("第三方返回數據");}}return this.execute(new CallBackHand());}public <T> T execute(ICallBackHand<T> backHand) {System.out.println("獲取第三方的客戶工具");return backHand.doInState("第三方返回結果");}public static void main(String[] args) {Person person = new Person();person.query("hello", cho -> {System.out.println("返回需要的執行結果");return new Man();});}}interface ICallBackHand<T> {T doInState(String manJson); }@FunctionalInterface interface ResultSetExtractor<T> {T extractData(String cho); }?二十、Reactor模式(I/O服務模型)?
- Reactor 的叫法:?1. 反應器模式 2. 分發者模式(Dispatcher) 3. 通知者模式(notifier)
? ? ? ? 也叫多路復用路由監聽處理
- 針對channel,java提供了nio包,也叫New IO,是由channel、buffer、selector組成。
? ? ? ?buffer:緩存數據,寫入渠道或從渠道讀取。
? ? ? ?channel:雙向(可讀寫),可以異步讀寫,只支持批量(buffer)讀寫
? ? ? ?selector:監聽多個渠道是否做好讀寫準備,配合非阻塞IO實現單個線程管理多個渠道。
二十一、備忘錄模式?????
? ? ? ? 也叫快照(Snapshot)模式,指在不違背封裝原則的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態,以便之后恢復對象為先前的狀態。主要用在數據防丟失,恢復,撤銷等場景,備忘錄模式更側重代碼的設計和實現,且備份對象僅僅可讀。
? ? ? ? 對大數據量處理時,可以針對不同應用場景指定合理的備份措施,如果需要做好原數據備份,可以采用低頻率全量備份和高頻率增量備份
二十二、解釋器模式
? ? ? ? 按照語法規則解釋,為不同應用場景提供支持
二十三、中介模式
? ? ? ? 定義了一個單獨的對象,來封裝一組對象之間的交互,將這組對象之間的交互委派給與中介對象交互,來避免對象之間的直接交互。
? ? ? ? 中介模式的設計思想和中間層很像,通過引入中介這個中間層,將一組對象之間的交互關系從多對多(網狀關系)轉換為一對多(星狀關系)。這組對象之間可以是單向交互也可以是雙向交互,適應錯綜復雜的應用場景,通過中介對象來統一調度。一般對象之間交互較為復雜時才考慮,比如飛機航線的中臺...
總結
以上是生活随笔為你收集整理的java设计模式学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ArrayList数据去重的方法
- 下一篇: 测试显卡用什么软件最好,用什么软件能检测