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事件底層邏輯轉發
底層按鍵分發