Design pattern combat | iterator pattern | tokenizer

1. Scene

Assuming that there is a string attribute like the following, which represents the attribute 逐级调用, we need to parse out each field attribute to facilitate our subsequent business processing.

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

2. Traditional writing

Traverse the attribute string and continuously intercept each field, and then collect them into the collection in order

    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;
    }

operation result:insert image description here

3. Iterator mode

Based on the idea of ​​object-oriented processing and divide-and-conquer, it can be considered that the processing logic school.teacher[语文].student[3]of and teacher[语文].student[3]the processing logic of the substring are consistent. So you only need to iterate step by step to obtain the substring, and then hand over the substring to the logic for processing, and then the logic will continue to repeat, but the logical unit of processing becomes smaller.

/**
   分词单元:  负责将一个属性字符串分解成各个部分。 基于多态可扩展不同的分词单元。
*/
@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());
        }
    }
}

operation result:

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

4. Summary

  • Through improvement, the overall word segmentation logic is handed over to the specific iterative word segmenter. Different from the traditional writing method, if 每个属性单元there may be different processing logic, this method can still be extended, only need to obtain the specific word segmentation unit in the next without affecting the overall processing logic.
  • In fact, it is to put the external traversal logic into the recursive call of the object, 这个思想在许多场景里面是非常有用because the object is ok 多态的, and the specific processing logic of each state can be different, but the overall logic is the same, so in the end, the combined logic The number of branches is exponential. If you do not do this kind of processing and put them all in the external traversal processing, a large number of nested if elsebranch processing logic will be generated.
  • Of course, the iterator mode is mainly used 数据的迭代to separate the logic of different iterations of different data by creating different iterators. For example, here is a scene, and there are some complex data structure diagrams and trees. What kind of depth and breadth exist? Different iterators can be created for traversal and preorder traversal logic. So if your business data has its own different iteration logic, you can use this mode to process it.
  • Many people think that the binding of iterators and collections is the processing of collections, but this is only the so-called "collection" in a broad sense.本质是对数据的迭代, 这个数据可以是任何东西
  • Based on this idea, it is possible to expand other different attribute word segmentation processing logic

Guess you like

Origin juejin.im/post/7233996255101091901