Android设计模式------领域规则模式

本文深入探讨了解释器模式,一种用于处理固定文法问题的行为型设计模式。通过构建语法树和定义终结符与非终结符,解释器模式提供了一种灵活的解决方案,尤其适用于频繁变化的业务规则和重复出现的结构。文章通过一个加减运算表达式的实例,展示了如何使用解释器模式进行问题抽象和解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

"领域规则"模式

使用场景

在特定领域中,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域
下的一般性解决方案。

典型模式

Interpreter(解释器模式)

 


Interpreter 解释器模式

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

意图:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

主要解决:对于一些固定文法构建一个解释句子的解释器。

何时使用:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

如何解决:构建语法树,定义终结符与非终结符。

关键代码:构建环境类,包含解释器之外的一些全局信息,一般是 HashMap。

应用实例:编译器、运算表达式计算。

优点: 1、可扩展性比较好,灵活。 2、增加了新的解释表达式的方式。 3、易于实现简单文法。

缺点: 1、可利用场景比较少。 2、对于复杂的文法比较难维护。 3、解释器模式会引起类膨胀。 4、解释器模式采用递归调用方法。

使用场景: 1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。 2、一些重复出现的问题可以用一种简单的语言来进行表达。 3、一个简单语法需要解释的场景。

注意事项:可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。

使用场景

在软件构建过程中,如果某一特定领域的问题比较复杂,类似的结构不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。
在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
 

模式定义

给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。
 

类图结构

代码举例

简单的加减程序

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class MainActivity extends AppCompatActivity {

    private Button mExecuteButton;
    private TextView mResultText;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mExecuteButton = (Button) findViewById(R.id.execute_button);
        mResultText = (TextView) findViewById(R.id.result_text_view);

        mExecuteButton.setOnClickListener(listener);

    }


    View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
			//有了明确的规则 a,b,c,d,e 是操作数 + - 是操作符  a+b 之后 又变成新的操作数
            String expStr = "a+b-c+d-e";   
            Map<String, Integer> var = new HashMap<String, Integer>();
            var.put("a", 5);
            var.put("b", 2);
            var.put("c", 1);
            var.put("d", 6);
            var.put("e", 8);

			//analyse()将字符串表达式 解析成 表达式树
            Expression expression = Expression.analyse(expStr);
			
			//解析 表达式树 
            int result = expression.interpreter(var);
            mResultText.setText(expStr+ " = " + result);
        }
    };
}

Expression.java 

import java.util.Map;
import java.util.Stack;
//表达式的基类  使用表达式树 构成 语法规则
public abstract class Expression {

    public abstract int interpreter(Map<String, Integer> var);

    public static Expression analyse(String expStr) {
        Stack<Expression> expStack = new Stack<>();
        Expression left;
        Expression right;

        for (int i = 0; i < expStr.length(); i++) {
            switch (expStr.charAt(i)) {
                case '+':
                    //加法运算
                    left = expStack.pop(); //【1】 a   【7】 a + b - c
                    right = new VarExpression(expStr.charAt(++i)); //【2】 b  【8】 d
                    expStack.push(new AddExpression(left, right)); //【3】 a + b    【9】 a+b-c + d
                    break;
                case '-':
                    //减法运算
                    left = expStack.pop(); // 【4】a + b 
                    right = new VarExpression(expStr.charAt(++i)); // 【5】c
                    expStack.push(new SubExpression(left, right)); //【6】 a + b - c
                    break;
                default:
                    //变量表达式
                    expStack.push(new VarExpression(expStr.charAt(i)));

            }
        }
		
		//最终 栈顶 弹出的元素是  a+b-c+d
        Expression expression = expStack.pop();
        return expression;
    }

}

VarExpression.java 

import java.util.Map;

//变量表达式  a b c d e 都是变量表达式	
public class VarExpression extends Expression{

    char key;

    public VarExpression(char key) {
        this.key = key;
    }


    @Override
    public int interpreter(Map<String, Integer> var) {
		//变量表达式解决比较简单 取值即可
        return var.get(String.valueOf(key));
    }
}

SymbolExpression.java 

//符号表达式  + - * /
public abstract class SymbolExpression extends Expression{
    //运算符左右两个参数
    protected Expression left;
    protected Expression right;

    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
}

AddExpression.java 

import java.util.Map;

// + 表达式
public class AddExpression extends SymbolExpression {

    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }


    @Override
    public int interpreter(Map<String, Integer> var) {
		//解析的时候 取左边操作数 + 右边操作数
        return left.interpreter(var) + right.interpreter(var);
    }
}

SubExpression.java 

import java.util.Map;

// - 表达式
public class SubExpression extends SymbolExpression {

    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }

    @Override
    public int interpreter(Map<String, Integer> var) {
        return left.interpreter(var) - right.interpreter(var);
    }
}

 

表达式的语法树

 

类图结构中 Context 对应代码中的 MainActivity.java 中的 Map var。它就是上下文,传入相关参数。

AbstractExpression 对应代码中的 Expression。TerminalExpression 终端表达式,到此为止不能往下执行了,对应代码中的操作符a,b,c,d,即VarExpression类。NonterminalExpression 非终端表达式,即SymbolExpression(符号表达式), AddExpression 和 SubExpression。

 

要点总结

      Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。
     使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。

      Interpreter模式比较适合简单的文法表示,对于复杂的文法表示, Interperter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值