美文网首页
15、Android设计模式---(解决问题的第三者)迭代器模式

15、Android设计模式---(解决问题的第三者)迭代器模式

作者: flynnny | 来源:发表于2020-11-01 17:35 被阅读0次

一、介绍,定义

这个模式对开发者来说几乎不会自己去实现一个迭代器。所以对于这个模式更多的是在于理会其思想,而非应用。
提供一种方法顺序访问一个容器对象中的各个元素,而又不需要暴露该对象的内部表示。

二、使用场景

遍历一个容器对象

三、UML类图

19.png

Iterator : 迭代器接口,负责定义、访问、遍历元素的接口。
ConcreteIterator:具体的迭代类,实现迭代器接口,并记录遍历的当前位置。
Aggregate:容器接口,负责提供创建具体迭代器的接口。
ConcreteAggregate:具体容器类,和具体迭代器相关联。

四、通用代码

/**
 * 迭代器接口:负责定义、访问和遍历元素的接口
 * @param <T>
 */
public interface Iterator<T> {
    /**
     * 是否还有下一个对象
     * @return true:有; false:没有
     */
    boolean hasNext();
    /**
     * @return 返回当前位置的元素并将位置移至下一位
     */
    T next();
}
/**
 * 具体迭代器类:实现迭代器接口,并记录遍历的当前位置
 * 
 * @param <T>
 */
public class ConcreteIterator<T> implements Iterator<T> {

    private List<T> list = new ArrayList<T>();
    private int cursor = 0;

    public ConcreteIterator(List<T> list) {
        super();
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        return cursor != list.size();
    }

    @Override
    public T next() {
        T obj = null;
        if (this.hasNext()) {
            obj = this.list.get(cursor++);
        }
        return obj;
    }
}
/**
 * 容器接口:负责提供创建具体迭代器角色的接口
 * 
 * @param <T>
 */
public interface Aggregate<T> {
    /**
     * 添加一个元素
     * 
     * @param obj
     *            元素对象
     */
    void add(T obj);

    /**
     * 移除一个元素
     * 
     * @param obj
     *            元素对象
     */
    void remove(T obj);

    /**
     * 获取容器的迭代器
     * 
     * @return 迭代器对象
     */
    Iterator<T> iterator();
}
/**
 * 具体容器类:具体迭代器角色与该容器相关联
 * 
 * @param <T>
 */
public class ConcreteAggregate<T> implements Aggregate<T> {
    private List<T> list = new ArrayList<>();
    @Override
    public void add(T obj) {
        list.add(obj);
    }
    @Override
    public void remove(T obj) {
        list.remove(obj);
    }
    @Override
    public Iterator<T> iterator() {
        return new ConcreteIterator<>(list);
    }
}
/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        Aggregate<String> a = new ConcreteAggregate<>();
        a.add("hello1");
        a.add("hello2");
        a.add("hello3");
        a.add("hello4");
        a.add("hello5");

        Iterator<String> i = a.iterator();
        while (i.hasNext()) {
            System.out.println(i.next());
        }
    }
}

结果

hello1
hello2
hello3
hello4
hello5

五、简单实现

两个事业部统计各自员工数据,先为员工创建一个实体类:

public class Employee{
    private String name;
    private int age;
    private String sex;
    private String position;

    public Employee(String name ,int age,String sex,String position){
        this.name = name;
        this.age= age;
        this.sex= sex;
        this.position= position;
    }

    @Override
    public String toString (){
        return "Employee{"+
            "name='"+name+'\''+
            ",age="+age+
            ",sex="+sex+
            ",position = "+position+'\''+
            '}';
    }
}

为了简化代码就不提供set和get方法了,并在两个事业部中使用固定数据

public class CompanyA{
    private List<Employee> list = new ArrayList<>();

    public CompanyA(){
        list.add(new Employee("小民",96,"男","程序员")); 
        list.add(new Employee("小芸",22,"女","测试")); 
        list.add(new Employee("小方",18,"女","测试")); 
        list.add(new Employee("可儿",21,"女","设计")); 
        list.add(new Employee("朗晴",19,"女","设计")); 
   }
  
    public  List<Employee> getEmployees(){
        return list;
    }
}

public class CompanyB{
    private Employee[] array = new Employee[3];

    public CompanyB(){
        array[0]=new Employee("辉哥",108,"男","程序员");
        array[1]=new Employee("小红",98,"男","程序员");
        array[2]=new Employee("小辉",88,"男","程序员");
   }
  
    public  Employee[] getEmployees(){
        return array;
    }
}

所以查看时要变里两个容器:

public class Boss{
    public static void main(String [] args){
        CompanyA a = new CompanyA();
        List aList = a.getEmployees();
        for(int i = 0;i<aList.size();i++){
            System.out.println(aList.get(i).toString());
        }

        CompanyB b = new CompanyB();
        Employee[] bArray = b.getEmployees();
        for(int i = 0;i<bArray .length;i++){
            System.out.println(bArray[i]);
        }
    }
}

如果还有其他部门,那么都要在Boss类中增加一段遍历逻辑,这时候用迭代器模式,将遍历封装。
定义一个迭代器接口:

public interface Iterator{
    // 是否还有下一个
    boolean hasNext();
    //返回当前元素,并将位置移动到下一位
    Object next();
}

分别对两个部门创建迭代器

public class AIterator implements Iterator{
    private List<Employee> list;
    private int position;

    public AIterator(List<Employee> list){
        this.list = list;
    }
    @Override
    public boolean hasNext(){
        return !(position>list.size-1||list.get(position)==null)
    }
    @Override
    public Object next(){
        Employee e = list.get(position);
        position++;
        return e;
    }
}

public class BIterator implements Iterator{
    private Employee[] array;
    private int position;

    public BIterator(Employee[] array){
        this.array= array;
    }
    @Override
    public boolean hasNext(){
        return !(position>array.length-1||array[position]==null)
    }
    @Override
    public Object next(){
        Employee e = array.[position];
        position++;
        return e;
    }
}

同时我们定义一个容器类的接口,能返回一个容器迭代器

public interface Company{
    Iterator iterator();
}

这时我们修改两个部门类实现容器接口,并返回对应的迭代器对象

public class CompanyA implements Company{
    private List<Employee> list = new ArrayList<>();

    public CompanyA(){
        list.add(new Employee("小民",96,"男","程序员")); 
        list.add(new Employee("小芸",22,"女","测试")); 
        list.add(new Employee("小方",18,"女","测试")); 
        list.add(new Employee("可儿",21,"女","设计")); 
        list.add(new Employee("朗晴",19,"女","设计")); 
   }
  
    public  List<Employee> getEmployees(){
        return list;
    }
    @Override
    public Iterator iterator(){
        return new AIterator(list);
    }
}

public class CompanyB implements Company{
    private Employee[] array = new Employee[3];

    public CompanyB(){
        array[0]=new Employee("辉哥",108,"男","程序员");
        array[1]=new Employee("小红",98,"男","程序员");
        array[2]=new Employee("小辉",88,"男","程序员");
   }
  
    public  Employee[] getEmployees(){
        return array;
    }
    @Override
    public Iterator iterator(){
        return new BIterator(array);
    }
}

最后在Boss中查阅时变得更简单

public class Boss{
    public static void main(String [] args){
        CompanyA a = new CompanyA();
        check(a.iterator());

        CompanyB b = new CompanyB();
        check(b.iterator());
    }
    
    private static void check(Iterator iterator){
        while(iterator.hasNext()){
            System.out.println(iterator.next().toString());
        }
    }
}

六、模式的优缺点:

迭代器就是把容器中遍历对象的功能提取出来,这样既不暴露容器的细节,又可以让外部访问容器内部的内容。
优点

  • 支持不同的方式去遍历一个容器,也可以有多个遍历,弱化了容器和遍历算法之间的关系。
  • 不用用户自己去实现遍历功能,也分离了容器和遍历算法,避免了容器承担过多功能。
  • 封装性更好,方便修改遍历算法而不用修改容器。
    缺点
  • 类文件会增加,所以对于简单的遍历来说不是很重要。

相关文章

网友评论

      本文标题:15、Android设计模式---(解决问题的第三者)迭代器模式

      本文链接:https://www.haomeiwen.com/subject/ewmlvktx.html