《Android源码设计模式解析与实战》读书笔记(十四)

第十四章、迭代器模式

迭代器模式,又叫做游标模式,是行为型设计模式之一。我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。

然而在前一种情况,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。第二种方式倒是省事,却又将容器的内部细节暴露无遗。

正因于此,迭代器模式应运而生,在客户访问类与容器体之间插入一个第三者–迭代器,很好的解决了上述弊端。

1.定义

提供一种方法顺序访问一个容器对象中的各个元素,而又不需要暴露该对象的内部表示。

2.使用场景

遍历一个容器对象时。

3.简单实现

用书中的例子:小民和小辉分别在公司两个事业部,某天老板安排任务让他们俩统计一下各自部门的员工数据。

员工实体类:

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) {
        super();
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.position = position;
    }

    // 简化代码,省略setter和getter方法

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

小辉部门:

public class CompanyHui {

private Employee[] array = new Employee[3];

    public CompanyHui(){
        array[0] = new Employee("辉哥", 28, "男", "程序猿");
        array[1] = new Employee("小红", 23, "男", "程序猿");
        array[2] = new Employee("小辉", 25, "男", "程序猿");
    }

    public Employee[] getEmployees(){
        return array;
    }
}

小民部门:

public class CompanyMin {

    private List<Employee> list = new ArrayList<>();

    public CompanyMin(){
        list.add(new Employee("小民", 26, "男", "程序猿"));
        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;
    }
}

Boss查看:

public class Boss {
    public static void main(String[] args) {
        CompanyHui hui = new CompanyHui();
        Employee[] huiList = hui.getEmployees();
        for(int i = 0; i < huiList.length; i++){
            System.out.println(huiList[i]);
        }

        CompanyMin min = new CompanyMin();
        List minList = min.getEmployees();
        for(int i = 0; i < minList.size(); i++){
            System.out.println(minList.get(i).toString());
        }
    }
}

结果:

Employee{name=‘辉哥‘, age=28, sex=男, position=‘程序猿‘}
Employee{name=‘小红‘, age=23, sex=男, position=‘程序猿‘}
Employee{name=‘小辉‘, age=25, sex=男, position=‘程序猿‘}
Employee{name=‘小民‘, age=26, sex=男, position=‘程序猿‘}
Employee{name=‘小芸‘, age=22, sex=女, position=‘测试‘}
Employee{name=‘小方‘, age=18, sex=女, position=‘测试‘}
Employee{name=‘可儿‘, age=21, sex=女, position=‘设计‘}
Employee{name=‘朗情‘, age=19, sex=女, position=‘设计‘}

这样看似也没有问题,但是如果有多个部门,每个部门有各自的实现,那么我们就要在Boss类中增加一遍遍历逻辑,这样Boss类的功能会越来越多,同时暴露了内部细节。那么我们需要定义一个迭代器接口:

public interface Iterator {

    /**
     * 是否还有下一个元素
     *
     * @return true表示有,false表示没有
     */
    boolean hasNext();

    /**
     * 返回当前元素,并将位置移至下一位
     */
    Object next();
}

小民的迭代器:

public class MinIterator implements Iterator{

    private List<Employee> list;
    private int position;

    public MinIterator(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 HuiIterator implements Iterator{

    private Employee[] array;
    private int position;

    public HuiIterator(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 {

    /**
     * 返回一个迭代器对象
     *
     * @return 迭代器对象
     */
    Iterator iterator();

}

修改一下之前的两个容器类:

public class CompanyHui implements Company{

    private Employee[] array = new Employee[3];

    public CompanyHui(){
        array[0] = new Employee("辉哥", 28, "男", "程序猿");
        array[1] = new Employee("小红", 23, "男", "程序猿");
        array[2] = new Employee("小辉", 25, "男", "程序猿");
    }

    public Employee[] getEmployees(){
        return array;
    }

    @Override
    public Iterator iterator() {
        return new HuiIterator(array);
    }
}
public class CompanyMin implements Company{

    private List<Employee> list = new ArrayList<>();

    public CompanyMin(){
        list.add(new Employee("小民", 26, "男", "程序猿"));
        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 MinIterator(list);
    }
}

Boss查看:

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

        CompanyMin min = new CompanyMin();
        check(min.iterator());
    }

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

结果不变,就不重复写了。

4.Android源码中的模式实现

1.Cursor

当我们使用SQLiteDatabase的query方法查询数据库时,会返回一个Cursor游标对象,该游标的实质就是一个具体的迭代器,我们可以使用它来遍历数据库查询所得的结果集。

5.总结

迭代器模式发展至今,几乎所有的高级语言都有相应的内置实现,对于开发者而言,已经极少会自己去实现迭代器了,所以本章内容更多的是了解而非应用。

1.优点

(1)符合面向对象设计原则中的单一职责原则。

(2)支持对容器对象的多种遍历。弱化了容器类与遍历算法之间的关系。

2.缺点

(1)类文件的增加。

(3)会出现ConcurrentModificationException异常。

(2)遍历过程是一个单向且不可逆的遍历。

6.参考

深入浅出Java设计模式之迭代器模式

ConcurrentModificationException异常

时间: 2024-10-26 19:50:39

《Android源码设计模式解析与实战》读书笔记(十四)的相关文章

《Android源码设计模式解析与实战》读书笔记(十三)

第十三章.备忘录模式 备忘录模式是一种行为模式,该模式用于保存对象当前的状态,并且在之后可以再次恢复到此状态,有点像是我们平常说的"后悔药". 1.定义 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可将该对象恢复到原先保存的状态. 2.使用场景 (1)需要保存一个对象在某一个时刻的状态或部分状态. (2)如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访

《Android源码设计模式解析与实战》读书笔记(十八)

第十八章.代理模式 代理模式也称委托模式,是结构型设计模式之一.是应用广泛的模式之一. 1.定义 为其他对象提供一种代理以控制对这个对象的访问. 2.使用场景 当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口. 3.UML类图 (1)Subject:抽象主题类,声明真实主题与共同接口方法,该类可以是抽象类或接口. (2)RealSubject:真实主题类(被委托类),尤其执行具体的业务逻辑方法.

《Android源码设计模式解析与实战》读书笔记(二十二)

第二十二章.享元模式 享元模式是结构型设计模式之一,是对对象池的一种实现.就像它的名字一样,共享对象,避免重复的创建.我们常用的String 就是使用了共享模式,所以String类型的对象创建后就不可改变,如果当两个String对象所包含的内容相同时,JVM只创建一个String对象对应这两个不同的对象引用. 1.定义 采用一个共享来避免大量拥有相同内容对象的开销.使用享元模式可有效支持大量的细粒度对象. 2.使用场景 (1)系统中存在大量的相似对象. (2)细粒度的对象都具备较接近的外部状态,

《Android源码设计模式解析与实战》读书笔记(十一)

第十一章.命令模式 命令模式是行为型模式之一.总体来说并不难理解,只是比较繁琐,他会将简单的调用关系解耦成多个部分,增加类的复杂度,但是即便如此,命令模式的结构依然清晰. 1.定义 将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化:对请求排队或者记录请求日志,以及支持可撤销的操作. 2.使用场景 (1)需要抽出待执行的动作,然后以参数的形式提供出来. (2)在不同的时刻指定.排列和执行请求.一个命令对象可以有与初始请求无关的生存期. (3)需要支持操作取消. (4)支持修改日志功

《Android源码设计模式解析与实战》读书笔记(二十一)

第二十一章.装饰模式 装饰模式也称为包装模式,是结构型设计模式之一.装饰模式是一种用于替代继承技术的一种方案. 1.定义 动态的给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类更为灵活. 2.使用场景 (1)需要透明且动态地扩展类的功能时.且在不影响其他对象的情况下. (2)当不能采用继承对系统进行扩展时可以使用装饰模式.比如final类. 3.UML类图 (1)Component:抽象组件.可以是一个接口或抽象类,其充当的就是被装饰的原始对象. (2)ConcreteComp

《Android源码设计模式解析与实战》读书笔记(十二)

第十二章.观察者模式 观察者模式是一个使用率非常高的模式,它最常用在GUI系统.订阅–发布系统.因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小,甚至做到毫无依赖.比如安卓的开源项目EventBus.Otto.AndroidEventBus等事件总线类的和RxJava响应式编程其核心都是使用观察者模式. 1.定义 观察者模式是一种行为类模式,它定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新. 2.使用场景

《Android源码设计模式解析与实战》读书笔记(二十四)

第二十四章.桥接模式 桥接模式也称为桥梁模式,是结构型设计模式之一.桥接模式中体现了"单一职责原则"."开闭原则"."里氏替换原则"."依赖倒置原则"等.同时它也是很实用的一种模式. 1.定义 将抽象部分与现实部分分离,使它们都可以独立地进行变化. 2.使用场景 (1)如果一个系统需要在构建的抽象化角色和具体角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系. (2)对于那些不希望使用继承或因为多层次继承导致系统类

《Android源码设计模式解析与实战》读书笔记(十)

第十章.解释器模式 解释器模式是一种用的比较少的行为型模式,其提供了一种解释语言的语法或表达式的方式.但是它的使用场景确实很广泛,只是因为我们自己很少回去构造一个语言的文法,所以使用较少. 1.定义 给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子.(其中语言就是我们需要解释的对象,文法就是这个语言的规律,解释器就是翻译机,通过文法来翻译语言.) 2.使用场景 1.如果某个简单的语言需要解释执行而且可以将该语言中的语句表示为一个抽象的语法树时可以考虑使

《Android源码设计模式解析与实战》读书笔记(八)

第八章.状态模式 1.定义 状态模式中的行为是由状态来决定,不同的状态下有不同的行为.当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 2.使用场景 1.一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为. 2.代码中包含大量与对象状态有关的条件语句,例如,一个操作中含有大量的多分支语句,且这些分支依赖于该对象的状态. 3.简单实现 实现效果:首先将电视的状态分为开机与关机状态,开机时可以通过遥控器实现频道切换和调节音量,但是关机时,这些操作都会失效.