设计模式访问者模式-迭代器模式-观察者模式
- 访问者模式
-
基本介绍
- 访问者模式,封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作。
- 主要将数据结构和数据操作分离,解决数据结构和操作耦合性问题。
- 访问者模式的工作原理:在被访问的类里面加一个对外提供接待访问者的接口。
- 访问者模式主要应用场景是:需要对一个对象结构中的对象进行很多不同操作(这些操作彼此没有关联),同时需要避免让这些操作“污染”这些对象的类,可以选用访问者模式解决。
-
代码
public abstract class Action { //得到男人的测评结果 public abstract void getManResult(Man man); //得到女人的测评结果 public abstract void getWomanResult(Woman woman); } public class Fail extends Action { @Override public void getManResult(Man man) { System.out.println("男性给歌手的测评结果是失败"); } @Override public void getWomanResult(Woman woman) { System.out.println("女性给歌手的测评结果是失败"); } } public class Success extends Action { @Override public void getManResult(Man man) { System.out.println("男性给歌手的测评结果是成功"); } @Override public void getWomanResult(Woman woman) { System.out.println("女性给歌手的测评结果是成功"); } } public abstract class Person { public abstract void accept(Action action); } public class Man extends Person{ @Override public void accept(Action action) { action.getManResult(this); } } /** * 1.在这里我们使用到了双分派,即首先在客户端程序中, * 将具体状态作为参数传递到woman中(第一次分派) * 2.然后woman类调用作为参数的‘具体方法’中的getWomanResult, * 同时将自己作为参数传入, * @author Administrator * */ public class Woman extends Person{ @Override public void accept(Action action) { action.getWomanResult(this); } } import java.util.LinkedList; import java.util.List; public class ObjectStructure { private List<Person> persons=new LinkedList<Person>(); public void attach(Person p) { persons.add(p); } public void detach(Person p) { persons.remove(p); } public void display(Action action) { for (Person person : persons) { person.accept(action); } } } public class Client { public static void main(String[] args) { ObjectStructure obStructure=new ObjectStructure(); obStructure.attach(new Man()); obStructure.attach(new Woman()); Success success=new Success(); obStructure.display(success); System.out.println("=================="); Fail fail=new Fail(); obStructure.display(fail); } }
-
双分派:
- 所谓双分派是指不管类怎么变化,我们都能找到期望的方法运行。双分派意味着得到执行的操作取决于请求的种类和两个接收者的类型。
- 以上述实例为例,假设我们需添加一个eliminatet的状态类,考察Man类和Woman类的反应,由于使用了双分派,只需要增加一个Action的子类,即可在客户端调用即可,不需要改动任何其他类的代码。
-
访问者模式的注意事项和细节
- 优点:
- 访问者模式符合单一职责原则、让程序具有优秀的扩展性、灵活性非常高。
- 访问者模式化可以对功能进行统一,可以做报表、ui、拦截器与过滤器,适用于数据结构相对稳定的系统。
- 缺点:
- 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的,这样造成了具体元素变更比较困难。
- 违背了依赖倒转原则。访问者依赖的具体元素,而不是抽象元素。
- 因此,如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的。
- 优点:
-
- 迭代器模式
-
基本介绍:
- 迭代器模式是常用的设计模式,属于行为模式。
- 如果我们的集合元素是用不同的方式实现的,有数组还有java的集合类,或者还有其它方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。
- 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层实现表示,即:不暴露其内部结构。
-
代码
//系 public class Department { private String name; private String describe; public Department(String name, String describe) { this.name = name; this.describe = describe; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDes() { return describe; } public void setDes(String describe) { this.describe = describe; } } public class ComputerCollegeIterator implements Iterator<Object> { //这里我们需要Department是怎样存在的 private Department[] departments; private int posiition; public ComputerCollegeIterator(Department[] departments) { this.departments = departments; } //判断是否有 下一个 @Override public boolean hasNext() { if(posiition>=departments.length||departments[posiition]==null) { return false; } return true; } @Override public Object next() { Department department = departments[posiition]; posiition+=1; return department; } //删除的方法默认空实现 @Override public void remove() { } } public class InfoCollegeIterator implements Iterator<Object> { //这里我们需要Department是怎样存在的 private List<Department> departments; private int index=-1; public InfoCollegeIterator(List<Department> departments) { this.departments = departments; } //判断是否有 下一个 @Override public boolean hasNext() { if(index>=departments.size()-1) { return false; } index+=1; return true; } @Override public Object next() { return departments.get(index); } //删除的方法默认空实现 @Override public void remove() { } } public interface College { public String getName(); public void addDepartment(String name,String describe); public Iterator<Object> createIterator(); } public class ComputerCollege implements College { private Department[] departments; int numOfDepartment=0; public ComputerCollege() { departments=new Department[5]; addDepartment("java专业","java专业"); addDepartment("php专业","php专业"); addDepartment("大数据专业","大数据专业"); addDepartment("python专业","python专业"); } @Override public Iterator<Object> createIterator() { return new ComputerCollegeIterator(departments); } @Override public String getName() { return "计算机学院"; } @Override public void addDepartment(String name, String describe) { Department department = new Department(name, describe); departments[numOfDepartment]=department; numOfDepartment++; } } public class InfoCollege implements College { private List<Department> departments; int numOfDepartment=0; public InfoCollege() { departments=new ArrayList<Department>(); addDepartment("信息安全专业", "信息安全专业"); addDepartment("网络安全专业", "网络安全专业"); addDepartment("服务器安全专业", "服务器安全专业"); } @Override public String getName() { return "信息工程学院"; } @Override public void addDepartment(String name, String describe) { Department department = new Department(name, describe); departments.add(department); } @Override public Iterator<Object> createIterator() { return new InfoCollegeIterator(departments); } } public class OutputIml { private List<College> collegeList; public OutputIml(List<College> collegeList) { this.collegeList = collegeList; } public void printCollege() { Iterator<College> iterator = collegeList.iterator(); while (iterator.hasNext()) { College college = iterator.next(); System.out.println("========"+college.getName()+"==========="); printDepartment(college.createIterator()); } } public void printDepartment(Iterator<Object> iterator) { while (iterator.hasNext()) { Department department = (Department)iterator.next(); System.out.println(department.getName()); } } } public class Client { public static void main(String[] args) { List<College> collegeList = new ArrayList<College>(); ComputerCollege computerCollege = new ComputerCollege(); InfoCollege infoCollege=new InfoCollege(); collegeList.add(computerCollege); collegeList.add(infoCollege); OutputIml outputIml=new OutputIml(collegeList); outputIml.printCollege(); } }
-
迭代器模式的注意事项和细节
- 优点:
- 提供了一个统一的方法遍历对象,客户不用在考虑聚合的类型,使用一种方法就可以遍历对象了。
- 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的内部结构。
- 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。
- 当要展示一组相似对象,或者遍历一组相同的对象时使用,适合使用迭代器模式。
- 缺点:
- 每个聚合对象都需要有一个迭代器,会产生多个迭代器类不好管理。
- 优点:
-
- 观察者模式
-
基本原理
- 对象之间对对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化。
-
代码
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void nodifyObservers(); } public class WeatherData implements Subject { private float temperature; private float pressure; private float humidity; private List<Observer> observers; public WeatherData() { observers=new ArrayList<Observer>(); } public float getTemperature() { return temperature; } public float getPressure() { return pressure; } public float getHumidity() { return humidity; } @Override public void registerObserver(Observer o) { if(!observers.contains(o)) { observers.add(o); } } @Override public void removeObserver(Observer o) { if(observers.contains(o)) { observers.remove(o); } } public void setData(float temperature,float pressure,float humidity) { this.temperature=temperature; this.pressure=pressure; this.humidity=humidity; nodifyObservers(); } //遍历所有的观察者通知 @Override public void nodifyObservers() { for (int i = 0; i < observers.size(); i++) { observers.get(i).update(temperature, pressure, humidity); } } } //观察者接口 public interface Observer { public void update(float temperature,float pressure,float humidity); } public class CurrentCondition implements Observer { private float temperature; private float pressure; private float humidity; @Override 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 temperayure"+temperature); System.out.println("Today pressure"+pressure); System.out.println("Today humidity"+humidity); } } public class BaiDu implements Observer { private float temperature; private float pressure; private float humidity; @Override 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 temperayure"+temperature); System.out.println("百度Today pressure"+pressure); System.out.println("百度Today humidity"+humidity); } }
-
观察者模式的好处
- 观察者模式设计后,会以集合的方式来管理用户,包括注册,移除和通知。
- 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类,遵守ocp原则。
-