設計模式筆記之十五 (解釋器模式)

解釋器模式express

解釋器模式就是定義一種語言,並定義這個語言的解釋器,解釋器可以按照定義好的語法來將這種語言‘翻譯’成使用者能理解的語言。數組

普遍上來說,Java是一種定義的語言,JVM就是一種‘解釋器’,而計算機就是最終的使用者。咱們寫一段Java代碼,而計算機只認識0101的機器語言,JVM就是將Java代碼解釋成0101的機器語言讓計算機可以理解並運行。ide

咱們仍是以咱們實驗室的實例來講明下這個模式。this

 

最近咱們實驗室的獸人工廠拿到了老總的一個批示:spa

class LaoZong {
    private String order = "MN1n2";

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }
    
}

class ShouRenFactory {
    public void readOrder() {
        LaoZong lz = new LaoZong();
        System.out.println(lz.getOrder());
    }
}

public class Interpreter {
    public static void main(String[] args) {
        new ShouRenFactory().readOrder();
    }
}

 因而獸人工廠拿到老闆的指令就是"MN1n2"。徹底不明白要幹什麼,因而須要找老闆祕書來解釋下:翻譯

class ShouRenFactory {
    public void readOrder() {
        LaoZong lz = new LaoZong();
        MiShu ms = new MiShu();
        
        System.out.println(ms.translate(lz.getOrder()));
    }
}

class MiShu {
    public String translate(String order) {
        //Black Box
        String realWord = "生產男獸人1個女獸人2個";
        return realWord;
    } 
}

如今咱們獸人工廠終於知道了老總的命令:"生產男獸人1個女獸人2個", 可是祕書是怎麼知道老總的命令的呢,若是獸人工廠也能知道祕書解析的過程,那就不用每次都麻煩祕書來解釋了。畢竟祕書是老闆用的,而不是獸人工廠用的。code

請教祕書解析的方法:blog

祕書說她先判斷每個字幕或者數組是什麼類型的命令,而後再用不一樣的解釋方法解釋不一樣的類型,好比說‘M’就是命令類的,‘Nn’是產品名稱類的,數字就是數量類的。get

因而獸人工廠就根據祕書的方法實現了本身的解析方式:產品

public class Interpreter {
    public static void main(String[] args) {
        new ShouRenFactory().readOrder();
    }
}

class ShouRenFactory {
    private String translate(String order) {
        String realOrder = "";
        
        //組裝解釋器
        List<Expression> expressions = new ArrayList<Expression>();
        expressions.add(new CommandExpression());
        expressions.add(new ProductExpression());
        expressions.add(new NumberExpression());
        
        //挨個解釋老總的命令
        String[] codes = order.split("");
        for (String code :codes) {
            for (Expression expression : expressions) {
                if (expression.matches(code)) {
                    realOrder += expression.excute(code);
                    break;
                }
            }
        }
        
        return realOrder;
    }
    public void readOrder() {
        LaoZong lz = new LaoZong();

        System.out.println(translate(lz.getOrder()));
    }
}

abstract class Expression {
    protected HashMap<String, String> map = new HashMap<String, String>();

    private Set<String> getMarkers() {
        return map.keySet();
    }

    public boolean matches(String code) {
        return getMarkers().contains(code);
    }

    abstract public String excute(String code);
}

class CommandExpression extends Expression {

    public CommandExpression() {
        map.put("M", "建立");
        map.put("D", "銷燬");
        map.put("E", "維修");
    }

    @Override
    public String excute(String code) {
        return map.get(code);
    }
}

class ProductExpression extends Expression {

    public ProductExpression() {
        map.put("N", "男獸人");
        map.put("n", "女獸人");
    }

    @Override
    public String excute(String code) {
        return map.get(code);
    }
}

class NumberExpression extends Expression {

    public NumberExpression() {
    }

    @Override
    public boolean matches(String code) {
        return code.matches("[0-9]");
    }
    
    @Override
    public String excute(String code) {
        return code + "個";
    }
}

這樣咱們就實現了一個簡單的解析器模式,在這種模式下,咱們能夠很簡單的增長或者刪除某種解析器。

 

 

解析器模式是一種易於理解但難於應用的模式。 除非在「一種特定類型的問題發生的頻率足夠高」的狀況下,咱們並不推薦使用此模式。由於當文法特別複雜時,會產生不少類,這對維護來講比較困難。總的來講在文法比較簡單且發生頻率很高的狀況下才使用此模式。

相關文章
相關標籤/搜索