第10章 第1節 設計模式

● 請你說一下常用設計模式;

參考回答:

(1)單例模式:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,避免一個全局使用的類頻繁的創建和銷燬,節省系統資源,提高程序效率。實現方式:將被實現的類的構造方法設計成private的。添加此類引用的靜態成員變量,併爲其實例化。在被實現的類中提供公共的Create Instance函數,返回實例化的此類,就是2中的靜態成員變量。單例模式只允許創建一個對象,因此節省內存,加快對象訪問速度,適用場景:需要頻繁實例化然後銷燬的對象。創建對象時耗時過多或者耗資源過多,但又經常用到的對象。有狀態的工具類對象。頻繁訪問數據庫或文件的對象。場景舉例:每臺計算機有若干個打印機,但只能有一個PrinterSpooler,以避免兩個打印作業同時輸出到打印機;Windows的TaskManager(任務管理器),不能打開兩個windows task manager;Windows的Recycle Bin(回收站),在整個系統運行過程中,回收站一直維護着僅有的一個實例;網站的計數器,一般也是採用單例模式實現,否則難以同步;(2)策略模式:策略模式是把一個類中經常改變或者將來可能改變的部分提取出來作爲一個接口,然後在類中包含這個對象的實例,這樣類的實例在運行時就可以隨意調用實現了這個接口的類的行爲。實現方式:提供公共接口或抽象類,定義需要使用的策略方法。(策略抽象類)多個實現的策略抽象類的實現類。(策略實現類)環境類,對多個實現類的封裝,提供接口類型的成員量,可以在客戶端中切換。客戶端調用環境類進行不同策略的切換。類圖:圖片Strategy:策略接口,用來約束一系列具體的策略算法。Context使用這個接口來調用具體的策略,實現定義的策略。ConcreteStrategy:具體的策略實現,也就是具體的算法實現。Context:上下文,負責與具體的策略交互,通常上下文會持有一個真正的策略實現。適用場景:如果在一個系統裏面有許多類,它們之間的區別僅在於它們的行爲,那麼使用策略模式可以動態地讓一個對象在許多行爲中選擇一種行爲。一個系統需要動態地在幾種算法中選擇一種。一個類定義了多種行爲, 並且這些行爲在這個類的操作中以多個條件語句的形式出現。將相關的條件分支移入它們各自的Strategy類中以代替這些條件語句。(3)簡單工廠模式:定義一個用於創建對象的接口或抽象類,讓子類決定實例化哪一個類,工廠方法使一個類的實例化延遲到其子類。類圖:圖片實現方式:抽象產品類(Product),是所創建的所有對象的父類,負責描述所有實例所共有的公共接口多個具體的產品類(Concrete Product),具體產品角色是創建目標,所有創建的對象都充當這個角色的某個具體類的實例。工廠類(Creator),負責實現創建所有實例的內部邏輯適用場景:在任何需要生成複雜對象的地方,都可以使用工廠方法模式。當需要系統有比較好的擴展性時,可以考慮工廠模式,不同的產品用不同的實現工廠來組裝。(4)裝飾模式:允許向一個現有的對象添加新的功能,同時又不改變其結構,以在不使用創造更多子類的情況下,將對象的功能加以擴展。類圖:圖片實現方式:抽象構件(Component)角色:給出一個抽象接口,以規範準備接收附加責任的對象。具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類。裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。具體裝飾(ConcreteDecorator)角色:負責給構件對象“貼上”附加的責任。適用場景:擴展一個類的功能。動態增加功能,動態撤銷。(5)觀察者模式:對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。類圖:圖片抽象主題(Subject)角色:把所有對觀察者對象的引用保存在一個集合中,每個抽象主題角色都可以有任意數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者角色。一般用一個抽象類和接口來實現。抽象觀察者(Observer)角色:爲所有具體的觀察者定義一個接口,在得到主題的通知時更新自己。具體主題(ConcreteSubject)角色:在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。具體主題角色通常用一個子類實現。具體觀察者(ConcreteObserver)角色:該角色實現抽象觀察者角色所要求的更新接口,以便使本身的狀態與主題的狀態相協調。通常用一個子類實現。如果需要,具體觀察者角色可以保存一個指向具體主題角色的引用。適用場景:當一個抽象模型有兩個方面, 其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和複用。當對一個對象的改變需要同時改變其它對象, 而不知道具體有多少對象有待改變。當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之, 你不希望這些對象是緊密耦合的。

● 請你手寫一下單例模式

參考回答:

1、餓漢模式

public class Singleton {private static Singleton instance = new Singleton();private Singleton (){}public static Singleton getInstance() {return instance;}}
這種方式在類加載時就完成了初始化,所以類加載較慢,但獲取對象的速度快。這種方式基於類加載機制避免了多線程的同步問題,但是也不能確定有其他的方式(或者其他的靜態方法)導致類裝載,這時候初始化instance顯然沒有達到懶加載的效果。 2、懶漢模式(線程不安全)
public class Singleton {private static Singleton instance;private Singleton (){}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}
懶漢模式申明瞭一個靜態對象,在用戶第一次調用時初始化,雖然節約了資源,但第一次加載時需要實例化,反映稍慢一些,而且在多線程不能正常工作。 3、懶漢模式(線程安全)
public class Singleton {private static Singleton instance;private Singleton (){}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}
這種寫法能夠在多線程中很好的工作,但是每次調用getInstance方法時都需要進行同步,造成不必要的同步開銷,而且大部分時候我們是用不到同步的,所以不建議用這種模式。 4、雙重檢查模式 (DCL)
public class Singleton {private volatile static Singleton singleton;private Singleton (){}public static Singleton getInstance() {if (instance== null) {synchronized (Singleton.class) {if (instance== null) {instance= new Singleton();}}}return singleton;}}
這種寫法在getSingleton方法中對singleton進行了兩次判空,第一次是爲了不必要的同步,第二次是在singleton等於null的情況下才創建實例。

● 請問設計模式是什麼?

參考回答:

設計模式(Design pattern)代表了最佳的實踐,通常被有經驗的面向對象的軟件開發人員所採用。設計模式是軟件開發人員在軟件開發過程中面臨的一般問題的解決方案。這些解決方案是衆多軟件開發人員經過相當長的一段時間的試驗和錯誤總結出來的。設計模式是一套被反覆使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是爲了重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。毫無疑問,設計模式於己於他人於系統都是多贏的,設計模式使代碼編制真正工程化,設計模式是軟件工程的基石,如同大廈的一塊塊磚石一樣。項目中合理地運用設計模式可以完美地解決很多問題,每種模式在現實中都有相應的原理來與之對應,每種模式都描述了一個在我們周圍不斷重複發生的問題,以及該問題的核心解決方案,這也是設計模式能被廣泛應用的原因。

● 請你手寫一下單例模式代碼

參考回答:

懶漢式單例模式:延遲實例化,但節省空間package com.sxh.singleton;public class SingleTon {/** volatile關鍵字確保:當uniqueInstance變量被初始化爲SingleTon實例時,多個線程能正確的處理uniqueInstance變量* 分析:volatile修飾的成員變量,在每次被線程訪問時,都強制性的從共享內存重讀該成員的值;* 當值發生變化是,強制線程將變化值寫入共享內存,任何時候不同線程總是看到你某個成員變量的同一個值* */private volatile static SingleTon uniqueInstance;//利用一個靜態變量來記錄SingleTon類的唯一實例//其他有用的單件類的數據
private SingleTon(){} //類外無法訪問public  static SingleTon getInstance(){/** 使用”雙重檢查加鎖“,在getInstance中減少使用同步* 首先檢查是否實例已經創建了,如果尚未創建,才進行同步;只有第一次訪問getInstance會同步*/if(uniqueInstance==null){  //確保只有一個實例synchronized (SingleTon.class) { //多線程的情況不會出現問題,線程同步問題if(uniqueInstance==null){uniqueInstance=new SingleTon();//如果我們不需要這個實例,則永遠不會產生}}}return uniqueInstance;}//其他有用的單件類的方法,單件類也可以是一般的類,具有一般的數據和方法
}餓漢式單例模式:急切的創建實例,而不用延遲實例化
package com.sxh.singleton;public class SingleTon {
private volatile static SingleTon uniqueInstance=new SingleTon();//其他有用的單件類的數據
private SingleTon(){} //類外無法訪問public  static SingleTon getInstance(){return uniqueInstance;}//其他有用的單件類的方法,單件類也可以是一般的類,具有一般的數據和方法
}IoDH實現單例模式
package com.sxh.singleton;public class SingleTon {
private SingleTon(){} //類外無法訪問private static class HolderClass{ //靜態內部類private static final SingleTon uniqueinstance=new SingleTon();}public  static SingleTon getInstance(){return HolderClass.uniqueinstance;}//其他有用的單件類的方法,單件類也可以是一般的類,具有一般的數據和方法







圖片


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章