android源碼中使用的設計模式(行為型--解釋器模式,命令模式)

1.解釋器模式(Interpreter 化繁為簡的翻譯器)

1.1定義

給定一個語言,定義它的文法的一種表示,并定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。

解釋器模式

1.2使用場景

  • 語言需要解釋,并且該語言中的語句備用表示成一個抽象的語法樹
  • 在某些特定領域出現不斷重復的問題時,可以將該領域的問題轉化成為一種語法規則下的語句,然后構建解釋器來解釋該語句

1.3實現方法

1.提取解釋器共同點

public abstract class ArithmeticExpreesion {
    /**
     * 抽象的解析方法
     * 具體的解析邏輯由具體的子類實現
     * 
     */
    public abstract int interpret();
}

2.解釋器具體實現類

public class NumExpression extends ArithmeticExpreesion {
    private int num;
    public NumExpression(int num) {
        this.num = num;
    }
 
    @Override
    public int interpret() {
        return num;
    }
}
 
//抽象運算符
public abstract class OperatorExpression extends ArithmeticExpreesion {
    // 聲明成員變量存儲運算符兩邊的數字解釋器
    protected ArithmeticExpreesion exp1,exp2;
    
    public OperatorExpression(ArithmeticExpreesion exp1,ArithmeticExpreesion exp2){
        this.exp1 = exp1;
        this.exp2 = exp2;   
    }
}
//具體實現運算符
public class AdditionExpression extends OperatorExpression {
    
    public AdditionExpression(ArithmeticExpreesion exp1, ArithmeticExpreesion exp2) {
        super(exp1, exp2);
    }
    @Override
    public int interpret() {
        return exp1.interpret() + exp2.interpret();
    }
} 
 
public class SubtractionExpression extends OperatorExpression {
    public SubtractionExpression(ArithmeticExpreesion exp1, ArithmeticExpreesion exp2) {
        super(exp1, exp2);
    }
    @Override
    public int interpret() {
        return exp1.interpret() - exp2.interpret();
    }
}

3.業務處理

public class Calculator {
    // 聲明兩個ArithmeticExpression棧存儲并操作所有相關的解釋器
    private Stack<ArithmeticExpreesion> mExpStack = new Stack<ArithmeticExpreesion>();
    
    public Calculator(String expression){
        ArithmeticExpreesion exp1,exp2;
        
        String[] elements = expression.split(" ");
        
        for (int i = 0; i < elements.length; i++) {
            char key = elements[i].charAt(0);
            switch (key) {
                case '+':
                    //將棧中的解釋器彈出作為運算符號的左邊的解釋器
                    exp1 = mExpStack.pop();
                    // 同時將運算符符號數組下一個元素構造為一個數字解釋器
                    exp2 = new NumExpression(Integer.valueOf(elements[++i]));
                    mExpStack.push(new AdditionExpression(exp1, exp2));
                    break;
                case '-':
                    //將棧中的解釋器彈出作為運算符號的左邊的解釋器
                    exp1 = mExpStack.pop();
                    // 同時將運算符符號數組下一個元素構造為一個數字解釋器
                    exp2 = new NumExpression(Integer.valueOf(elements[++i]));
                    mExpStack.push(new SubtractionExpression(exp1, exp2));
                    break;
                default:
                    mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));
                    break;
            } 
        }
    }
    
    public int calculate(){
        return mExpStack.pop().interpret();
    } 
}
 

4.調用

public class Client {
    public static void main(String[] args) {
        String exp = "1 + 2 + 4 + 5 - 100";
        Calculator c = new Calculator(exp);
        System.out.println(exp + " = " + c.calculate());
    }
}

PS:在語法分析或者詞義分析中會用到

將一個具體的文法通過一個解釋器解釋, 把復雜的文法規則分離為簡單的功能進行解釋, 最后將其組合成一顆抽象的語法樹解釋執行, 至此, 可以看到解釋器模式的原理和本質: 將復雜的問題簡單化, 模塊化, 分離實現, 解釋執行

1.4 android源碼對應實現

最典型的是對配置文件AndroidManifest.xml文件的解析

PackageParser

PackageParser類為 Activity,service,provider等構件在其內部創建了對應的類,這個類其實對應配置文件中的一個個標簽,也就是一條文法。

Android中,某個apk文件的解析會用到PackageManagerService的scanPackageLI()方法,這是一個重載方法,在解析某個文件先調用第一種實現解析apk文件,再調用第二種實現將解析后的信息保存至PMS

private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,long currentTime, UserHandle user);
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,int scanFlags, long currentTime, UserHandle user)
PMS

2.命令模式

2.1定義

將一個請求封裝成一個對象,從而讓用戶使用不同的請求把客戶端參數化;對請求排隊或者記錄請求日志,以及支持可撤銷的操作。

命令模式

2.2 說明

  • Receiver是真正執行命令的對象。任何類都可能成為一個接收者,只要它能夠實現命令要求實現的相應功能。
  • Command命令角色:定義命令的接口,聲明具體命令類需要執行的方法。這是一個抽象角色。
  • concreteCommand:命令接口的具體實現對象,通常會持有接收者,并調用接收者的功能來完成命令要執行的操作。
  • Invoker請求者角色:負責調用命令對象執行請求,通常會持有命令對象(可以持有多個命令對象)。Invoker是Client真正觸發命令并要求命令執行相應操作的地方(使用命令對象的入口)。

2.3使用場景

  • 需要抽象出待執行的動作,然后以參數的形式提出來,類似過程設計中的回調
    -需要支持取消操作

2.4代碼實現

1.接收者

/***
 * 接收者角色
 */
public class TetrisMachine {
   public void toLeft(){
       System.out.println("向左");
   }
   
   public void toRight(){
       System.out.println("向右");
   }
   
   public void fastToButtom(){
       System.out.println("快速向下");
   }
   
   public void transform(){
       System.out.println("改變形狀");
   }
}

2.抽象命令和具體命令

/**
 * 命令者抽象
 */
public interface Command {
    /**
     * 命令執行方法
     */
   void execute();
}
 
public class LeftCommand implements Command {
    // 持有一個接收者
    private TetrisMachine machine;
 
    public LeftCommand(TetrisMachine machine) {
        this.machine = machine;
    }
 
    @Override
    public void execute() {
        machine.toLeft();
    }
}

3.請求者

public class Buttons {
    private LeftCommand leftCommand;
    private RightCommand rightCommand;
    private FallCommand fallCommand;
    private TransformCommand transformCommand;
 
    public void setLeftCommand(LeftCommand leftCommand) {
        this.leftCommand = leftCommand;
    }
 
    public void setRightCommand(RightCommand rightCommand) {
        this.rightCommand = rightCommand;
    }
 
    public void setFallCommand(FallCommand fallCommand) {
        this.fallCommand = fallCommand;
    }
 
    public void setTransformCommand(TransformCommand transformCommand) {
        this.transformCommand = transformCommand;
    }
 
    public void toLeft() {
        leftCommand.execute();
    }
 
    public void toRight() {
        rightCommand.execute();
    }
 
    public void fall() {
        fallCommand.execute();
    }
 
    public void changer() {
        transformCommand.execute();
    }
}
 

4.客戶端調用

public class Player {
 
    public static void main(String[] args) {
      TetrisMachine machine = new TetrisMachine();
      
      LeftCommand leftCommand = new LeftCommand(machine);
      RightCommand rightCommand =new RightCommand(machine);
      FallCommand fallCommand = new FallCommand(machine);
      TransformCommand transformCommand = new TransformCommand(machine);
      
      Buttons buttons = new Buttons();
      buttons.setLeftCommand(leftCommand);
      buttons.setRightCommand(rightCommand);
      buttons.setFallCommand(fallCommand);
      buttons.setTransformCommand(transformCommand);
      
      buttons.toLeft();
      buttons.toRight();
      buttons.fall();
      buttons.changer();
    }
}

2.5 android源碼中的實現

android事件底層邏輯轉發

底層按鍵分發
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容