Java-第十八部分-设计模式-迭代器模式和观察者模式

196 阅读3分钟

设计模式全文

迭代器模型

  • 案例,学校、学院、系;不同学院用不同的方式管理,计算机用数组,信息工程用集合
  • Iterator Pattern,行为型模式,当集合用不同的方式实现,当客户端要遍历这些集合,就需要多种遍历方式,暴露元素的内部结构

提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素 demo.png

  • 案例类图 demo2.png
  • 抽象集合
public interface College {
    String getName();
    void addDepartment(String name, String des);
    Iterator createIterator();
}
  • 实际的集合,以数组的方式存放元素
public class ComputeCollege implements College{
    Department[] departments;
    //保存当前数组的对象个数
    int numOfDepartment = 0;

    public ComputeCollege() {
        departments = new Department[5];
        addDepartment("java","java");
        addDepartment("go","go");
        addDepartment("oc","oc");
        addDepartment("python","python");
        addDepartment("swift","swift");
    }

    @Override
    public String getName() {
        return "Computer";
    }

    @Override
    public void addDepartment(String name, String des) {
        Department department = new Department(name, des);
        departments[numOfDepartment++] = department;
    }

    @Override
    public Iterator createIterator() {
        return new ComputerCollegeIterator(departments);
    }
}
  • ComputerCollegeIterator,针对于数组方式的迭代器
public class ComputerCollegeIterator implements Iterator {
    //需要知道Department的存放方式
    Department[] departments;
    //起始位置
    int position = 0;
    public ComputerCollegeIterator(Department[] departments) {
        this.departments = departments;
    }
    @Override
    public boolean hasNext() {
        return !(position >= departments.length || departments[position] == null);
    }

    @Override
    public Object next() {
        return departments[position++];
    }
    @Override
    public void remove() {
    }
}
  • 实际元素
public class Department {
    private String name;
    private String des;
    public Department(String name, String des) {
        this.name = name;
        this.des = des;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDes() {
        return des;
    }
    public void setDes(String des) {
        this.des = des;
    }
}
  • 输出类
public class OutputImpl {
    //学院集合
    List<College> colleges;
    public OutputImpl(List<College> colleges) {
        this.colleges = colleges;
    }
    //输出学院
    public void outputCollege() {
        Iterator<College> iterator = colleges.iterator();
        while (iterator.hasNext()) {
            College college = iterator.next();
            System.out.println(college.getName());
            outputDepatrment(college.createIterator());
        }
    }
    //学院输出系
    public void outputDepatrment(Iterator iterator) {
        while (iterator.hasNext()) {
            Department d = (Department) iterator.next();
            System.out.println(d.getName() + " - " + d.getDes());
        }
    }
}

ArrayList源码

demo3.png

  • 实现了list接口,有Iterator<E> iterator();得到迭代器的抽象方法 image.png
  • ArrayList的实现
public Iterator<E> iterator() {
    return new Itr();
}
  • ArrayList的内部类Itr image.png
  • ArrayList以数组形式存放,transient不会被序列化 image.png
  • 直接使用ArrayList元素 image.png

小结

  • 把管理对象集合和遍历对象集合则责任分开,符合单一责任原则,集合改变只影响聚合对象,遍历方式改变,只影响迭代器
  • 将迭代器隐含于集合的内部,一种方法遍历所有集合,具体实现根据存储的方式不同进行改变
  • 每个聚合对象都需要一个具体的迭代器,需要管理多个类

观察者模型

  • 案例,气象站,每天测量到温度、湿度等信息,设计API,更新时将信息发布
  • 传统方案,如果增加一个显示渠道,修改的地方较多 demo.png
  • Observer,需要端注册通知,推送端发送通知,遵守OCP原则 DEMO.png
  • Observer,观察者
public interface Observer {
    void update(float temperature, float pressure, float humidity);
}
  • Subject,管理者,管理观察者,负责监控信息变化
public interface Subject {
    void registerObserver(Observer o);
    void notifyObserver();
    void removeObserver(Observer o);
}
  • CurrentConditions,观察者的实现类
//显示网站
public class CurrentConditions implements Observer {
   // 温度气压
   private float temperature;
   private float pressure;
   private float humidity;
   //更新,被推送
   public void update(float temperature, float pressure, float humidity) {
      this.temperature = temperature;
      this.pressure = pressure;
      this.humidity = humidity;
      display();
   }
   public void display() {
      System.out.println("***Today mTemperature: " + temperature + "***");
      System.out.println("***Today mPressure: " + pressure + "***");
      System.out.println("***Today mHumidity: " + humidity + "***");
   }
}
  • WeatherData,消息源
public class WeatherData implements Subject{
    private float temperatrue;
    private float pressure;
    private float humidity;
    private List<Observer> observerList = new ArrayList<>();
    public void dataChange() {
        notifyObserver();
    }
    @Override
    public void registerObserver(Observer o) {
        observerList.add(o);
    }
    @Override
    public void notifyObserver() {
        for (Observer observer : observerList) {
            observer.update(temperatrue, pressure, humidity);
        }
    }
    @Override
    public void removeObserver(Observer o) {
        if (observerList.contains(o)) observerList.remove(o);
    }
    public void setData(float temperature, float pressure, float humidity) {
        this.temperatrue = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
    }
}

Observable源码

  • 管理观察者类,直接将接口实现,管理观察者 image.png
  • 观察者
public interface Observer {
    void update(Observable o, Object arg);
}
  • change为false时,标明这个数据源已将最新的更改通知给所有通知者,此时调用notify无效

那么在使用时,数据更新时要先将change设置为true image.png