1. 摘要
中介者模式可以把互相关联的两者解耦。这里的互相关联,就是关系数据库中的关联关系。如班级和学生的关系,每个班级有多个学生,但每个学生只属于一个班级。(关系数据库中的一对多关系)通过中介者模式,就能很好的实现一对多、多对多关系。本文仅介绍一对多的实现,多对多的实现与之类似,读者可举一反三。
2. 中介者模式UML图
3. 中介者模式实现
Mediator:
public class Mediator<MANY,ONE> {
private Map<MANY,ONE> mMany2One = new HashMap<>();
public ONE getOne(MANY many) {
return mMany2One.get(many);
}
public Set<MANY> getMany(ONE one) {
Set<MANY> set = new HashSet<>();
Iterator<Map.Entry<MANY,ONE>> i = mMany2One.entrySet().iterator();
while (i.hasNext()) {
Map.Entry<MANY,ONE> e = i.next();
if (e.getValue().equals(one)) {
set.add(e.getKey());
}
}
return set;
}
public void set(MANY many, ONE one) {
mMany2One.put(many, one);
}
}
public class Student {
private String mId;
private Mediator<Student, ClassRoom> mMediator;
public Student(String id, Mediator<Student, ClassRoom> mediator) {
mId = id;
mMediator = mediator;
}
public ClassRoom getClassRoom() {
return mMediator.getOne(this);
}
public void setClassRoom(ClassRoom classRoom) {
mMediator.set(this, classRoom);
}
@Override
public String toString() {
return "[Student id: " + mId + "]";
}
}
public class ClassRoom {
private String mId;
private Mediator<Student, ClassRoom> mMediator;
public ClassRoom(String id, Mediator<Student, ClassRoom> mediator) {
mId = id;
mMediator = mediator;
}
public Set<Student> getStudents() {
return mMediator.getMany(this);
}
public void addStudent(Student student) {
mMediator.set(student, this);
}
@Override
public String toString() {
return "[ClassRoom id: " + mId + "]";
}
}
4. 中介者模式实现多对多思路
可以使用List<Pair<F,S>>来代替一对多中Mediator的Map<MANY,ONE>对象。F为First的缩写,S为Second的缩写。使用Pair<F,S>来处理多对多关系,与关系数据库中,处理多对多关系的方式一样。举例来说,学生与课程是多对多的关系。假设,学生有三人,学生1、学生2、学生3,课程有两门,课程1、课程2。学生1选修了课程1,List<Pair<学生,课程>>就需要添加这一项Pair<学生,课程> pair11 = new Pair(学生1,课程1); 学生2选修了课程1和课程2,则List<Pair<学生,课程>>就需要再添加这两项Pair<学生,课程> pair21 = new Pair(学生2,课程1); 以及Pair<学生,课程> pair22 = new Pair(学生2,课程2); 学生3选修了课程2,则不再累述。
在Android中,Pair<F, S>实现如下:
package android.util;
import java.util.Objects;
/**
* Container to ease passing around a tuple of two objects. This object provides a sensible
* implementation of equals(), returning true if equals() is true on each of the contained
* objects.
*/
public class Pair<F, S> {
public final F first;
public final S second;
/**
* Constructor for a Pair.
*
* @param first the first object in the Pair
* @param second the second object in the pair
*/
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
/**
* Checks the two objects for equality by delegating to their respective
* {@link Object#equals(Object)} methods.
*
* @param o the {@link Pair} to which this one is to be checked for equality
* @return true if the underlying objects of the Pair are both considered
* equal
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) {
return false;
}
Pair<?, ?> p = (Pair<?, ?>) o;
return Objects.equals(p.first, first) && Objects.equals(p.second, second);
}
/**
* Compute a hash code using the hash codes of the underlying objects
*
* @return a hashcode of the Pair
*/
@Override
public int hashCode() {
return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
}
@Override
public String toString() {
return "Pair{" + String.valueOf(first) + " " + String.valueOf(second) + "}";
}
/**
* Convenience method for creating an appropriately typed pair.
* @param a the first object in the Pair
* @param b the second object in the pair
* @return a Pair that is templatized with the types of a and b
*/
public static <A, B> Pair <A, B> create(A a, B b) {
return new Pair<A, B>(a, b);
}
}
5. 引用
[1] 《设计模式Java手册》