デザインパターン戦闘 | イテレータパターン | トークナイザー

1. シーン

属性を表す次のような文字列属性があると仮定すると逐级调用、その後のビジネス処理を容易にするために各フィールド属性を解析する必要があります。

String properties = "school.teacher[语文].student[3].user[4].english.score";

2. 伝統的な書き方

属性文字列を走査し、各フィールドを継続的にインターセプトし、それらを順番にコレクションに収集します。

    public static void main(String[] args) {
        String properties = "school.teacher[语文].student[3].user[4].english.score";
        int index = -1;
        List<Unit> unitList = new ArrayList<>();
        while((index = properties.indexOf(".")) != -1){
            String prop = properties.substring(0,index);
            properties = properties.substring(index+1);
            Unit unit = new Unit();
            unit.setIndexedName(prop);
            if (prop.contains("[")){
                int ltIndex = prop.indexOf("[");
                unit.setName(prop.substring(0,ltIndex));
                unit.setIndex(prop.substring(ltIndex+1,ltIndex+2));
            }else {
                unit.setName(prop);
            }
            unitList.add(unit);
        }
    }
    
    @Data
    public static class Unit {
        private String indexedName;
        private String name;
        private String index;
    }

操作結果:ここに画像の説明を挿入

3. イテレータモード

オブジェクト指向処理と分割統治の考え方に基づき、属性文字列school.teacher[语文].student[3]teacher[语文].student[3]部分文字列の処理ロジックは整合していると考えることができます。したがって、部分文字列を取得するために段階的に繰り返すだけでよく、その後、その部分文字列を処理のためにロジックに渡します。その後、ロジックは繰り返しを続けますが、処理の論理単位は小さくなります。

/**
   分词单元:  负责将一个属性字符串分解成各个部分。 基于多态可扩展不同的分词单元。
*/
@Data
public  class PropertyUnit {

    private String fullName;
    private String indexedName;
    private String name;
    private String index;
    private String children;
    
    public PropertyUnit(String fullname) {
        this.fullName = fullname;
        int delim = fullname.indexOf('.');
        if (delim > -1) {
            name = fullname.substring(0, delim);
            children = fullname.substring(delim + 1);
        } else {
            name = fullname;
            children = null;
        }
        indexedName = name;
        delim = name.indexOf('[');
        if (delim > -1) {
            index = name.substring(delim + 1, name.length() - 1);
            name = name.substring(0, delim);
        }
    }
}
/**
	分词器:  
	    实现了迭代器, 通过将next方法将子串的处理交给下一个分词单元, 这样就可逐级迭代每个属性字段。
*/
public class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> {

    private PropertyUnit cur;

    public PropertyTokenizer(String fullName) {
        this.cur = new PropertyUnit("."+fullName);
    }

    @Override
    public Iterator<PropertyTokenizer> iterator() {
        return this;
    }

    @Override
    public boolean hasNext() {
        return cur.getChildren() != null;
    }

    @Override
    public PropertyTokenizer next() {
        this.cur = new PropertyUnit(this.cur.getChildren());
        return this;
    }

    public String getIndexedName() {
        return cur.getIndexedName();
    }

    public String getFullName() {
        return cur.getFullName();
    }

    public String getName() {
        return cur.getName();
    }

    public String getIndex() {
        return cur.getIndex();
    }

    public String getChildren() {
        return cur.getChildren();
    }


    public static void main(String[] args) {
       String properties = "school.teacher[语文].student[3].user[4].english.score";
        
        // 迭代器遍历
        Iterator<PropertyTokenizer> iterator = new PropertyTokenizer(properties).iterator();
        while (iterator.hasNext()) {
            PropertyTokenizer next = iterator.next();
            System.out.println(next.getIndexedName());
        }

        System.out.println("==========");
        
        // 增强for循环遍历
        PropertyTokenizer tokenizer1 = new PropertyTokenizer(properties);
        for (PropertyTokenizer propertyTokenizer1 : tokenizer1) {
            System.out.println(propertyTokenizer1.getIndexedName());
        }
    }
}

操作結果:

school
teacher[语文]
student[3]
user[4]
english
score

4. まとめ

  • 改善により、単語セグメンテーション ロジック全体が特定の反復単語セグメンターに引き継がれます。従来の書き込み方法とは異なり、每个属性单元処理ロジックが異なる場合でも、この方法は全体の処理ロジックに影響を与えることなく、次の特定の単語分割単位を取得するだけで拡張できます。
  • 実際、これは、オブジェクトの再帰呼び出しに外部トラバーサル ロジックを組み込むことです。这个思想在许多场景里面是非常有用オブジェクトは ok であるため多态的です。各状態の特定の処理ロジックは異なる場合がありますが、全体的なロジックは同じなので、最終的には、結合ロジック 分岐数は指数関数的であるため、このような処理を行わずにすべて外部トラバーサル処理に入れてしまうと、入れ子の分岐処理ロジックが大量に生成されてしまいますif else
  • もちろん、イテレータ モードは主に、数据的迭代異なるイテレータを作成することによって、異なるデータの異なる反復のロジックを分離するために使用されます。たとえば、これはシーンであり、いくつかの複雑なデータ構造図とツリーがあります。どのような深さと幅が存在するか? トラバーサル ロジックとプリオーダー トラバーサル ロジックに対して異なる反復子を作成できます。したがって、ビジネス データに独自の異なる反復ロジックがある場合は、このモードを使用してデータを処理できます。
  • イテレータとコレクションのバインディングがコレクションの処理だと思っている人も多いですが、これはいわゆる広義の「コレクション」にすぎません。本质是对数据的迭代, 这个数据可以是任何东西
  • この考え方に基づいて、他の異なる属性語分割処理ロジックを拡張することが可能です

おすすめ

転載: juejin.im/post/7233996255101091901