一、迭代器模式
1、概述
1、迭代器(Iterator)模式:
提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素, 不需要知道集合对象的底层表示(即:不暴露其内部的结构)。迭代器模式是一种对象行为型模式。
2、主要角色
1、抽象迭代器(Iterator):定义访问和遍历聚合元素的接口,通常包含hasNext()、next()、remove()等方法。
2、具体迭代器(Concretelterator):实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
3、抽象聚合(Aggregate):定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
4、具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
3、迭代器模式实现
public class InfoColleageIterator implements Iterator {
List<Department> list;
public InfoColleageIterator(List<Department> list) {
this.list = list;
}
int index = -1;
@Override
public boolean hasNext() {
if (index >= list.size() - 1) {
return false;
} else {
index += 1;
return true;
}
}
@Override
public Object next() {
return list.get(index);
}
}
public class ComputerCollegeIterator implements Iterator {
Department[] departments;
public ComputerCollegeIterator(Department[] departments) {
this.departments = departments;
}
int position = 0;
@Override
public boolean hasNext() {
if (position >= departments.length || departments[position] == null) {
return false;
}
return true;
}
@Override
public Object next() {
Department department = departments[position];
position += 1;
return department;
}
}
@Data
@AllArgsConstructor
public class Department {
private String name;
private String desc;
}
public interface ColleageAggregate {
public String getName();
public void add(String name,String desc);
public Iterator createIterator();
}
public class InfoAggregate implements ColleageAggregate {
List<Department> departments;
public InfoAggregate() {
departments = new ArrayList<>();
add("信息安全","保障信息安全");
add("数据库安全","保障数据库安全");
add("服务器安全","保障服务器安全");
}
@Override
public String getName() {
return "信息工程学院";
}
@Override
public void add(String name, String desc) {
Department department = new Department(name, desc);
departments.add(department);
}
@Override
public Iterator createIterator() {
return new InfoColleageIterator(departments);
}
}
public class ComputerAggregate implements ColleageAggregate {
Department[] departments;
public ComputerAggregate() {
departments = new Department[5];
add("Java","后台服务");
add("MySQL","提供数据");
add("HTML + CSS","美化页面");
}
int num = 0;
@Override
public String getName() {
return "计算机学院";
}
@Override
public void add(String name, String desc) {
Department department = new Department(name, desc);
departments[num] = department;
num += 1;
}
@Override
public Iterator createIterator() {
return new ComputerCollegeIterator(departments);
}
}
public class Client {
public static void main(String[] args) {
List<ColleageAggregate> colleage = new ArrayList<>();
ComputerAggregate colleageAggregate = new ComputerAggregate();
InfoAggregate infoAggregate = new InfoAggregate();
colleage.add(colleageAggregate);
colleage.add(infoAggregate);
Iterator<ColleageAggregate> iterator = colleage.iterator();
while (iterator.hasNext()) {
ColleageAggregate next = iterator.next();
System.out.println("==========" + next.getName() + "==========");
Iterator iterator1 = next.createIterator();
while (iterator1.hasNext()) {
Department department = (Department) iterator1.next();
System.out.println(department.getName());
}
}
}
}
4、优缺点说明
1、优点:
-
提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
-
隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
-
它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
-
增加新的聚合类和迭代器类都很方便,无须修改原有代码。
-
封装性良好,为遍历不同的聚合结构提供一个统一的接口。
2、缺点:
-
增加了类的个数,这在一定程度上增加了系统的复杂性。
5、应用场景
1、当需要为聚合对象提供多种遍历方式时。
2、当需要为遍历不同的聚合结构提供一个统一的接口时。
3、当访问一个聚合对象的内容而无须暴露其内部细节的表示时。
4、总结:
由于聚合与迭代器的关系非常密切,所以大多数语言在实现聚合类时都提供了迭代器类,因此大数情况下使用语言中已有的聚合类的迭代器就已经够了。
二、观察者模式
1、概述
1、观察者(Observer)模式:
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。
2、主要角色
1、抽象主题(Subject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
2、具体主题(Concrete Subject):也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
3、抽象观察者(Observer):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
4、具体观察者(Concrete Observer):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
3、观察者模式实现
public interface Subject {
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver();
}
@Getter
public class ConcreteSubject implements Subject {
private float temperature;
private float pressure;
private float humidity;
private ArrayList<Observer> observers;
public ConcreteSubject() {
observers = new ArrayList<Observer>();
}
public void setData(float temperature,float pressure,float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
dataChange();
}
public void dataChange(){
notifyObserver();
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if (observers.contains(observer)) {
observers.remove(observer);
}
}
@Override
public void notifyObserver() {
for (int i = 0; i < observers.size(); i++) {
observers.get(i).update(this.temperature,this.pressure,this.humidity);
}
}
}
public interface Observer {
void update(float temperature,float pressure,float humidity);
}
public class ConcreteObserver 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();
}
private void display() {
System.out.println("温度:" + temperature);
System.out.println("气压:" + pressure);
System.out.println("湿度:" + humidity);
}
}
public class Client {
public static void main(String[] args) {
ConcreteSubject concreteSubject = new ConcreteSubject();
ConcreteObserver concreteObserver = new ConcreteObserver();
concreteSubject.addObserver(concreteObserver);
System.out.println("通知各个观察者。查看信息");
concreteSubject.setData(19f,100f,30f);
}
}
4、优缺点说明
1、优点:
-
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
-
目标与观察者之间建立了一套触发机制。
2、缺点:
-
目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
-
当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
5、应用场景
1、在软件系统中,当系统一方行为依赖另一方行为的变动时,可使用观察者模式松耦合联动双方,使得一方的变动可以通知到感兴趣的另一方对象,从而让另一方对象对此做出响应。
-
对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
-
当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
-
实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。
-
多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知。
三、中介者模式
1、概述
1、中介者(Mediator)模式:
定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。
2、主要角色
1、抽象中介者(Mediator):它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
2、具体中介者(Concrete Mediator):实现中介者接口,定义一个集合来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
3、抽象同事类(Colleague):定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
4、具体同事类(Concrete Colleague):是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
3、中介者模式实现
public abstract class Mediator {
public abstract void register(Colleague colleague);
public abstract void relay(Colleague cl);
}
public class ConcreteMediator extends Mediator {
private List<Colleague> colleagues = new ArrayList<Colleague>();
@Override
public void register(Colleague colleague) {
if (!colleagues.contains(colleague)) {
colleagues.add(colleague);
colleague.setMedium(this);
}
}
@Override
public void relay(Colleague cl) {
for (Colleague ob : colleagues) {
if (!ob.equals(cl)) {
((Colleague) ob).receive();
}
}
}
}
public abstract class Colleague {
protected Mediator mediator;
public void setMedium(Mediator mediator) {
this.mediator = mediator;
}
public abstract void receive();
public abstract void send();
}
public class ConcreteColleague1 extends Colleague {
@Override
public void receive() {
System.out.println("具体同事类1收到请求。");
}
@Override
public void send() {
System.out.println("具体同事类1发出请求。");
mediator.relay(this);
}
}
public class ConcreteColleague2 extends Colleague {
@Override
public void receive() {
System.out.println("具体同事类2收到请求。");
}
@Override
public void send() {
System.out.println("具体同事类2发出请求。");
mediator.relay(this);
}
}
public class Client {
public static void main(String[] args) {
Mediator md = new ConcreteMediator();
Colleague c1, c2;
c1 = new ConcreteColleague1();
c2 = new ConcreteColleague2();
md.register(c1);
md.register(c2);
c1.send();
System.out.println("=================");
c2.send();
}
}
4、优缺点说明
1、优点:
-
类之间各司其职,符合迪米特法则。
-
降低了对象之间的耦合性,使得对象易于独立地被复用。
-
将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
2、缺点:
-
中介者模式将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事类越多时,中介者就会越臃肿,变得复杂且难以维护。
5、应用场景
1、当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时。
2、当想创建一个运行于多个类之间的对象,又不想生成新的子类时。si
四、备忘录模式
1、概述
1、备忘录(Memento)模式:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
2、主要角色
1、发起人(Originator):记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
2、备忘录(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
3、管理者(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
3、备忘录模式实现
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento createMemento() {
return new Memento(state);
}
public void restoreMemento(Memento m) {
this.setState(m.getState());
}
}
@Data
@AllArgsConstructor
public class Memento {
private String state;
}
public class Caretaker {
private Memento memento;
public void setMemento(Memento m) {
memento = m;
}
public Memento getMemento() {
return memento;
}
}
public class Client {
public static void main(String[] args) {
Originator or = new Originator();
Caretaker cr = new Caretaker();
or.setState("S0");
System.out.println("初始状态:" + or.getState());
cr.setMemento(or.createMemento());
or.setState("S1");
System.out.println("新的状态:" + or.getState());
or.restoreMemento(cr.getMemento());
System.out.println("恢复状态:" + or.getState());
}
}
4、优缺点说明
1、优点:
-
提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
-
实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
-
简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。
2、缺点:
-
资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
5、应用场景
1、需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
2、需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。