1. 程式人生 > >Android 原始碼中的設計模式

Android 原始碼中的設計模式

面向物件的六大原則

  • 單一職責原則

      所謂職責是指類變化的原因。如果一個類有多於一個的動機被改變,那麼這個類就具有多於一個的職責。而單一職責原則就是指一個類或者模組應該有且只有一個改變的原因。通俗的說,即一個類只負責一項職責,將一組相關性很高的函式、資料封裝到一個類中。

  • 開閉原則

      對於擴充套件是開放的,這意味著模組的行為是可以擴充套件的。當應用的需求改變時,我們可以對模組進行擴充套件,使其具有滿足那些改變的新行為。 
      對於修改是關閉的,對模組行為進行擴充套件時,不必改動模組的原始碼。

      通俗的說,儘量通過擴充套件的方式實現系統的升級維護和新功能新增,而不是通過修改已有的原始碼。

  • 里氏替換原則

      使用“抽象(Abstraction)”和“多型(Polymorphism)”將設計中的靜態結構改為動態結構,維持設計的封閉性。任何基類可以出現的地方,子類一定可以出現。

      在軟體中將一個基類物件替換成它的子類物件,程式將不會產生任何錯誤和異常,反過來則不成立。在程式中儘量使用基類型別來對物件進行定義,而在執行時再確定其子類型別,用子類物件來替換父類物件。

  • 依賴倒置原則

      高層次的模組不應該依賴於低層次的模組,他們都應該依賴於抽象。抽象不應該依賴於具體實現,具體實現應該依賴於抽象。 
       
      程式要依賴於抽象介面,不要依賴於具體實現。簡單的說就是要求對抽象進行程式設計,不要對實現進行程式設計,這樣就降低了客戶與實現模組間的耦合(各個模組之間相互傳遞的引數宣告為抽象型別,而不是宣告為具體的實現類)。

  • 介面隔離原則

      一個類對另一個類的依賴應該建立在最小的介面上。其原則是將非常龐大的、臃腫的介面拆分成更小的更具體的介面。

  • 迪米特原則

      又叫作最少知識原則,就是說一個物件應當對其他物件有儘可能少的瞭解。 
      通俗地講,一個類應該對自己需要耦合或呼叫的類知道得最少,不關心被耦合或呼叫的類的內部實現,只負責呼叫你提供的方法。

      下面開始設計模式學習...  

1. Singleton(單例模式)

作用:  

保證在Java應用程式中,一個類Class只有一個例項存在。

好處:

由於單例模式在記憶體中只有一個例項,減少了記憶體開銷。

 單例模式可以避免對資源的多重佔用,例如一個寫檔案時,由於只有一個例項存在記憶體中,避免對同一個資原始檔的同時寫操作。 
   
單例模式可以再系統設定全域性的訪問點,優化和共享資源訪問。

使用情況:

建立目錄 資料庫連線的單執行緒操作

某個需要被頻繁訪問的例項物件 

1.1 使用方法

第一種形式:

public class Singleton {

    /* 持有私有靜態例項,防止被引用,此處賦值為null,目的是實現延遲載入 */
    private static Singleton instance = null;

    /* 私有構造方法,防止被例項化 */
    private Singleton() {
    }

    /* 懶漢式:第一次呼叫時初始Singleton,以後就不用再生成了
    靜態方法,建立例項 */
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

  但是這有一個問題,不同步啊!在對據庫物件進行的頻繁讀寫操作時,不同步問題就大了。

第二種形式

  既然不同步那就給getInstance方法加個鎖唄!我們知道使用synchronized關鍵字可以同步方法和同步程式碼塊,所以:  

 public static synchronized Singleton getInstance() {  
     if (instance == null) {  
         instance = new Singleton();  
     }  
     return instance;  
 } 
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

或是

public static Singleton getInstance() {  
     synchronized (Singleton.class) {  
         if (instance == null) {  
             instance = new Singleton();  
         }  
     }  
     return instance;  
 } 
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

獲取Singleton例項:

Singleton.getInstance().方法()
  
  • 1

1.2android中的Singleton

軟鍵盤管理的 InputMethodManager

原始碼(以下的原始碼都是5.1的):

205 public final class InputMethodManager {
//.........
211     static InputMethodManager sInstance;
//.........
619     public static InputMethodManager getInstance() {
620         synchronized (InputMethodManager.class) {
621             if (sInstance == null) {
622                 IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
623                 IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
624                 sInstance = new InputMethodManager(service, Looper.getMainLooper());
625             }
626             return sInstance;
627         }
628     }
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

  使用的是第二種同步程式碼塊的單例模式(可能涉及到多執行緒),類似的還有 
  AccessibilityManager(View獲得點選、焦點、文字改變等事件的分發管理,對整個系統的除錯、問題定位等) 
  BluetoothOppManager等。

當然也有同步方法的單例實現,比如:CalendarDatabaseHelper

307     public static synchronized CalendarDatabaseHelper getInstance(Context context) {
308         if (sSingleton == null) {
309             sSingleton = new CalendarDatabaseHelper(context);
310         }
311         return sSingleton;
312     }
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意Application並不算是單例模式

44 public class Application extends ContextWrapper implements ComponentCallbacks2 {

79     public Application() {
80         super(null);
81     }
  
  • 1
  • 2
  • 3
  • 4
  • 5

在Application原始碼中,其構造方法是公有的,意味著可以生出多個Application例項,但為什麼Application能實現一個app只存在一個例項呢?請看下面:

在ContextWrapper原始碼中:

50 public class ContextWrapper extends Context {
51     Context mBase;
52 
53     public ContextWrapper(Context base) {
54         mBase = base;
55     }

64     protected void attachBaseContext(Context base) {
65         if (mBase != null) {
66             throw new IllegalStateException("Base context already set");
67         }
68         mBase = base;
69     }
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ContextWrapper建構函式傳入的base為null, 就算有多個Application例項,但是沒有通過attach()繫結相關資訊,沒有上下文環境,三個字。

然並卵

2. Factory(工廠模式)

 定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工廠方法使一個類的例項化延遲到其子類。 
 對同一個介面的實現類進行管理和例項化建立

這裡寫圖片描述 

假設我們有這樣一個需求:

  動物Animal,它有行為move()。有兩個實現類cat和dog。為了統一管理和建立我們設計一個工廠模式。 
  同時兩個子類有各自的行為,Cat有eatFish(),Dog有eatBone().

結構圖: 
這裡寫圖片描述

Animal介面:

interface animal {
    void move();
}
  
  • 1
  • 2
  • 3

Cat類:

public class Cat implements Animal{

    @Override
    public void move() {
        // TODO Auto-generated method stub
        System.out.println("我是隻肥貓,不愛動");
    }
    public void eatFish() {  
        System.out.println("愛吃魚");
    } 
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Dog類:

public class Dog implements Animal{

    @Override
    public void move() {
        // TODO Auto-generated method stub
        System.out.println("我是狗,跑的快");
    }
    public void eatBone() {  
        System.out.println("愛吃骨頭");
    } 
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

那麼現在就可以建一個工廠類(Factory.java)來對例項類進行管理和建立了.

public class Factory {
    //靜態工廠方法
    //多處呼叫,不需要例項工廠類 
     public static Cat produceCat() {  
            return new Cat();  
        } 
     public static Dog produceDog() {  
            return new Dog();  
        }
//當然也可以一個方法,通過傳入引數,switch實現
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

使用:

Animal cat = Factory.produceCat();
cat.move();
//-----------------------------
Dog dog = Factory.produceDog();
dog.move();
dog.eatBone();
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  工廠模式在業界運用十分廣泛,如果都用new來生成物件,隨著專案的擴充套件,animal還可以生出許多其他兒子來,當然兒子還有兒子,同時也避免不了對以前程式碼的修改(比如加入後來生出兒子的例項),怎麼管理,想著就是一團糟。

Animal cat = Factory.produceCat();
  
  • 1

 這裡例項化了Animal但不涉及到Animal的具體子類(減少了它們之間的偶合聯絡性),達到封裝效果,也就減少錯誤修改的機會。

  Java面向物件的原則,封裝(Encapsulation)和分派(Delegation)告訴我們:具體事情做得越多,越容易範錯誤,

  一般來說,這樣的普通工廠就可以滿足基本需求。但是我們如果要新增一個Animal的實現類panda,那麼必然要在工廠類裡新增了一個生產panda的方法。就違背了 閉包的設計原則(對擴充套件要開放對修改要關閉) ,於是有了抽象工廠模式。

2.1 Abstract Factory(抽象工廠)

  抽象工廠模式提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。 
  啥意思?就是把生產抽象成一個介面,每個例項類都對應一個工廠類(普通工廠只有一個工廠類),同時所有工廠類都繼承這個生產介面

生產介面Provider:

interface Provider {
    Animal produce(); 
}
  
  • 1
  • 2
  • 3

每個產品都有自己的工廠 
CatFactory:

public class CatFactory implements Provider{

    @Override
    public Animal produce() {
        // TODO Auto-generated method stub
        return 
            
           

相關推薦

Spring原始碼設計模式

我對設計模式的理解: 應該說設計模式是我們在寫程式碼時候的一種被承認的較好的模式,就像一種宗教信仰一樣,大多數人承認的時候,你就要跟隨,如果你想當一個社會存在的話。好的設計模式就像是給程式碼造了一個很好的骨架,在這個骨架裡,你可以知道心在哪裡,肺在哪裡,因為大多數人都認識這

Android 原始碼設計模式

面向物件的六大原則 單一職責原則   所謂職責是指類變化的原因。如果一個類有多於一個的動機被改變,那麼這個類就具有多於一個的職責。而單一職責原則就是指一個類或者模組應該有且只有一個改變的原因。通俗的說,即一個類只負責一項職責,將一組相關性很高的函式、資料封裝到一個類中。

android原始碼設計模式

建造者模式 建造者模式最明顯的標誌就是Build類,而在Android中最常用的就是Dialog的構建,Notification的構建也是標準的建造者模式。 建造者模式很好理解,如果一個類的構造需要很多引數,而且這些引數並不都是必須的,那麼這種情況下就比較適合Builder。 比如構建一

Android設計模式-Builder模式

遇到多個構造器引數時要考慮使用構建器 引入:當我們建立物件傳遞引數的時候,往往通過構造方法來傳,如下程式碼: public class Person { private String name; private String id;

Android設計模式--狀態模式(將動作委託到當前狀態,狀態之間可以互相轉換)

   狀態模式:將狀態封裝成為獨立類,並將動作委託到當前狀態;狀態之間可以相互轉換,因為實現了相同的介面;狀態改變,則動作會跟著改變。  理解: 1.定義狀態介面,所有的狀態均實現該介面,這樣對於客戶(呼叫者)來說,狀態是可以替換的,客戶不關心具體的狀態是什麼,只是呼叫介

Android設計模式MVC,MVP,MVVM的簡單理解

設計模式VS框架框架是程式碼的重用,可擴充套件。舉幾個簡單的例子。Spring架構,Struts架構。設計模式是設計的重用,是一種抽象的設計方法。例如MVC,MVP,MVVM。下面,我們以android開發為例,簡單比較一下三種不同的設計模式。MVCMVC是指Modle,Vi

Android設計模式之單例模式的種類

Android開發設計模式中的單例模式       單例模式是設計模式中最常見也最簡單的一種設計模式,保證了在程式中只有一個例項存在並且能全域性的訪問到。比如在android實際APP 開發中用到的 賬號資訊物件管理, 資料庫物件(SQLiteOpenHelp

ANDROID 設計模式的採用--結構型模式

       在GOF所著的設計模式經典著作中對橋接模式與介面卡模式的區別描述為:B r i d g e模式的結構與物件介面卡類似,兩個模式的不同之處主要在於它們各自的用途和出發點:B r i d g e目的是將介面部分和實現部分分離和橋接,從而對它們可以較為容易也相對獨立的加以改變和演化,B r i d

android深入之設計模式(一)托付模式

-h listen back != new 聚合 string static data- (一)托付模式簡單介紹 托付模式是主要的設計模式之中的一個。托付。即是讓還有一個對象幫你做事情。 更多的模式,如狀態模式、策略模式、訪問者模式本質上是在更特殊的場合採用了托

java23設計模式之適配器模式

print 鍵盤 分享 rri sys 完成 out img closed package com.bjsxt.adapter; /** * 被適配的類 * (相當於例子中的,PS/2鍵盤) * @author Administrator * */

Java 23設計模式

叠代 職責鏈模式 方法 備忘錄模式 創建型 抽象工廠 適配器 狀態模式 橋接模式 創建型模式(5):   --單例模式、工廠模式、抽象工廠模式、建造者模式、原型模式。 結構型模式(7):   --適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。 行為

java23設計模式之叠代器模式

asn spl gre ring ext concrete sta get face package com.bdqn.iterator; public interface MyIterator { //將遊標指向第一個元素 void first()

java23設計模式之策略模式

log author 批量 isp contex view strategy ext 不同 package com.bjsxt.strategy; /** * 負責和具體的策略類交互 * 這樣的話,具體的算法和直接的客戶端調用分離了,使得算法可以獨立於客戶端獨立

Android與MVC設計模式

wikipedia 數據模型 後來 small 事先 wiki 兩個 修改 idt 寫在前面,之前做過一段時間移動開發,後來因為工作原因擱淺了,最新重新拿起Android權威編程指南學習,順道做個學習筆記。 首先呢,我想說無論是計算機科班出身還是培訓班出身,都聽說過高內聚

java23設計模式之代理模式

唱歌 [] lap pen 技術分享 contract rac display images staticproxy ---靜態代理 package com.bjsxt.proxy.staticProxy; public interface Star

23設計模式包括哪些

單例模式 自動更新 %20 att 技術 讓其 emp 直接 獲得 傳送門(轉載):https://www.cnblogs.com/Leo_wl/p/6067267.html 附(github設計模式):https://github.com/iluwatar/java-d

Android源碼設計模式》學習筆記之ImageLoader

format trac dir nload download 活性 thread 大內存 idg 微信公眾號:CodingAndroid cnblog:http://www.cnblogs.com/angel88/ CSDN:http://blog.csdn.net

Android原始碼引用@hide類出現引用異常的問題error: cannot find symbol

    自己開發的APP在Android中使用一些系統隱藏的類         編譯的時候報錯,出現如下異常 error: cannot find symbol import android.net.EthernetM

java23設計模式之觀察者模式

什麼叫觀察者模式? 當被觀察者的資料更新時,將會通知觀察該主題的所有觀察者。就像---微信公眾號就是被觀察者---關注該公眾號的就是觀察者---》 當公眾號更新文章時,關注的人就會獲得該資訊。這就是觀察者模式的應用。 用圖說明: 下面將用程式碼來解釋上面的內容: 1.觀

php的23設計模式

原文地址 https://my.oschina.net/botkenni/blog/1603660   PhpDesignPatterns 【PHP 中的設計模式】 一、 Introduction【介紹】 設計模式:提供了一種廣泛的可重用的方式來解決我們日常