1. 程式人生 > >設計模式-中介者模式(Java實現)

設計模式-中介者模式(Java實現)

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);
    }

}
Student:
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 + "]";
    }
}
ClassRoom:
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手冊》