中介者模式小试

中介者模式是一个设计模式中非常重要的一个模式,是我们模块设计中经常会用到的。

一、介绍

那么什么是中介者模式呢?

《研磨设计模式》中有这样的定义——用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。

中介者模式的本质是——封装交互。

前面学过外观模式,外观模式的本质是“封装交互,简化调用”,那么中介者模式和外观模式有什么区别呢?

外观模式是用来封装子系统之间的各个模块,向子系统外部提供简单易用的接口。就是说,外观模式封装子系统之间的交互是为了让外部系统调用的时候更加方便,交互的方向是单项的。而中介者模式是纯粹为了简化各个内部模块之间,多向的交互。

 

二、结构

1、Mediator——中介者接口,定义了各同事类交互的方法。

2、ConcreteMediator——中介者实现类,持有各个同事类。

3、Colleague——同事类,通常为抽象类,持有中介者对象,发生改变时,调用中介者对象所定义的同事类交互的方法。

4、ConcreteColleague——同事类的实现类。

 

三、我的实现:

中介者模式是怎么实现的呢?

假设有这样的需求,要模拟当当网的整个送货流程。有这样几点要求:

1、主要有顾客、当当网、取货中心、送货中心、快递员这样几个模块。

2、其中,顾客下订单、取货中心取货、送货中心送货、快递员送货这几个行为结束之后,都必须通知当当网,以便顾客随时获取信息。

3、另外还有一个实体类——订单。

这里,由于各个模块之间进行交互,可以把当当网作为我们的中介者。这里是我自己的大体实现:

1、首先是订单实体类:

//订单类,实体Bean
public class Order {
  
// 联系人信息
    private String personInfomation;
  
// 送货地址
    private String address;
  
// 商品列表
    private String productList;
//Get Set方法省略
}

2、其次,做了一个抽象类,以便扩展,有一个通知当当网的方法,其他需要通知当当网的类都继承这个类。

public abstract class Notice {

  
// 通知Dangdang的方法
    public void noticeDangdang(Notice notice) {
      
//Dangdang的处理消息的方法。
        Dangdang.getInstance().executeNotice(notice);
    }
}

3、然后就是顾客类,继承了Notice类,如下:

public class Customer extends Notice{

  
private Order order;
   
  
public Order getOrder() {
      
return order;
    }

  
public void sendOrder(Order order) {
      
this.order = order;
      
//通知当当
        noticeDangdang(this);
    }

}

4、取货中心:

//取货中心,设置为单例
public class GetProductsCenter extends Notice {

  
private static GetProductsCenter center = new GetProductsCenter();
  
public static GetProductsCenter getInstance(){
      
return center;
    }
   
  
// 取货
    public void getProduct(Order order) {
        System.out.println(
"从仓库取得" + order.getProductList());
      
// 通知当当
        noticeDangdang(this);
    }
}

5、送货中心:

import java.util.LinkedList;

//送货中心,设置为单例
public class SendProductsCenter extends Notice {
   
  
private static SendProductsCenter center = new SendProductsCenter();
  
public static SendProductsCenter getInstance(){
      
return center;
    }

  
// 同步的送货人列表,这里真正实现时,应该与数据库交互
    public LinkedList<DeliveryMan> deliveryManList = new LinkedList<DeliveryMan>();

  
public void addDeliveryMan(DeliveryMan deliveryMan) {
        deliveryManList.push(deliveryMan);
    }

  
private DeliveryMan getDeliveryMan() {
      
return deliveryManList.poll();
    }

  
// 送货人去送货
    public void sendProducts(Order order) {
        init();
        DeliveryMan deliveryMan
= getDeliveryMan();
      
//通知当当
        noticeDangdang(this);
        deliveryMan.findCustomerAndSendProducts(order);
    }

  
public void init(){
        DeliveryMan man
= new DeliveryMan();
        addDeliveryMan(man);
    }
}

6、送货员:

public class DeliveryMan extends Notice {
   private String deliveryManName = "张三";

  
public String getDeliveryManName() {
      
return deliveryManName;
    }

  
public void setDeliveryManName(String deliveryManName) {
      
this.deliveryManName = deliveryManName;
    }

  
// 找到顾客并送货
    public void findCustomerAndSendProducts(Order order) {
        System.out.println(
"我是送货员,货物到达" + order.getAddress());
        noticeDangdang(
this);
    }
}

7、然后就是最重要的中介者类——当当网:

import java.util.LinkedList;

//中介者类为单例
public class Dangdang {

  
private static Dangdang instance = new Dangdang();

  
// 一个同步的订单列表,这里真正实现时,应该为数据库中取出
    public LinkedList<Order> orderList = new LinkedList<Order>();

  
public static Dangdang getInstance() {
      
return instance;
    }

  
public void addOrderToList(Order order) {
        orderList.push(order);
    }

  
private Order getOrderFromList() {
      
return orderList.poll();
    }

  
public void executeNotice(Notice notice) {
      
// 如果通知类是顾客
        if (notice.getClass() == Customer.class) {
            System.out.println(
"通知:已收到订单!开始处理订单!");
          
// 从顾客手中取得订单
            Order order = ((Customer) notice).getOrder();
          
// 开始处理订单
            executeOrder(order);
        }
      
// 如果通知类是取货中心
        if (notice.getClass() == GetProductsCenter.class) {
          
// 开始送货流程
            System.out.println("通知:取货成功,开始送货流程!");
        }
      
// 如果通知类是送货中心
        if (notice.getClass() == SendProductsCenter.class) {
            System.out.println(
"通知:分配送货人完毕,送货人开始送货!");
        }
      
if (notice.getClass() == DeliveryMan.class) {
            System.out.println(
"通知:送货员货已送到!");
        }
    }

  
// 处理订单流程
    public void executeOrder(Order order) {
      
// 增加订单到订单列表
        addOrderToList(order);
        beginToSend();
    }

  
// 开始送货
    public void beginToSend() {
      
// 从订单列表取得订单
        Order order = getOrderFromList();
      
// 取货中心去取货
        GetProductsCenter.getInstance().getProduct(order);
      
// 送货中心去送货
        SendProductsCenter.getInstance().sendProducts(order);

    }

}

8、我们来测试一下:

public class Test {

  
public static void main(String[] args) {
      
//创建顾客类
        Customer customer = new Customer();
      
//创建订单
        Order order = new Order();
        order.setAddress(
"广东省 广州市 XX路 XX号");
        order.setPersonInfomation(
"XXXXX的个人信息");
        order.setProductList(
"《程序员的自我修养》、《C++ Primer》");
        customer.sendOrder(order);
    }
}

9、结果如下:

通知:已收到订单!开始处理订单!
从仓库取得《程序员的自我修养》、《C++ Primer》
通知:取货成功,开始送货流程!
通知:分配送货人完毕,送货人开始送货!
我是送货员,货物到达广东省 广州市 XX路 XX号
通知:送货员货已送到!

四、解决多对多问题:

《研磨设计模式》在介绍中介者模式的时候,提出了一种用中介者模式解决数据多对多数据耦合的问题。

部门类Dep和人员类User,一个部门可以有多个人员,同样,一个人员可以属于多个部门。

而面对几种情况:1、部门被撤销 2、部门合并 3、人员离职 4、人员换部门

应该怎样处理呢?如果简单的用两个一对多的实体类来表示Dep和User,那就功能的实现就太复杂了。

1、首先定义部门类:

public class Dep {

  
private String depId;
  
private String depName;
  
public String getDepId() {
      
return depId;
    }
  
public void setDepId(String depId) {
      
this.depId = depId;
    }
  
public String getDepName() {
      
return depName;
    }
  
public void setDepName(String depName) {
      
this.depName = depName;
    }
  
//删除本部门,调用中介类处理
    public boolean deleteDep(){
        DepUserMediatorImpl mediator
= DepUserMediatorImpl.getInstance();
        mediator.deleteDep(depId);
      
return true;
       
    }
}

2、然后定义员工类:

public class User {

  
private String userId;
  
private String userName;
  
public String getUserId() {
      
return userId;
    }
  
public void setUserId(String userId) {
      
this.userId = userId;
    }
  
public String getUserName() {
      
return userName;
    }
  
public void setUserName(String userName) {
      
this.userName = userName;
    }
  
//员工离职,调用中介类处理
    public boolean dismission(){
        DepUserMediatorImpl mediator
= DepUserMediatorImpl.getInstance();
       
        mediator.deleteUser(userId);
      
return true;
       
    }
}

3、简单的员工-部门对应类,存储员工、部门的关系,如下:

public class DepUserModel {

  
private String depUserId;

  
private String depId;
  
private String userId;
  
public String getDepUserId() {
      
return depUserId;
    }

  
public void setDepUserId(String depUserId) {
      
this.depUserId = depUserId;
    }

  
public String getDepId() {
      
return depId;
    }

  
public void setDepId(String depId) {
      
this.depId = depId;
    }

  
public String getUserId() {
      
return userId;
    }

  
public void setUserId(String userId) {
      
this.userId = userId;
    }
   
}

4、然后是最重要的中介者类,如下:

//中介者类,设为单例
public class DepUserMediatorImpl {
   
  
private static DepUserMediatorImpl mediator = new DepUserMediatorImpl();
private Collection<DepUserModel> depUserList = new ArrayList<DepUserModel>();
   
  
public static DepUserMediatorImpl getInstance(){
      
return mediator;
    }
  
//删除部门
    public boolean deleteDep(String depId){
      
//一个临时列表 Collection<DepUserModel> tempList = new ArrayList<DepUserModel>();
      
for(DepUserModel model : depUserList){
          
if(model.getDepId().equals(depId)){
                tempList.add(model);
            }
        }
        depUserList.removeAll(tempList);
      
return true;
    }
  
//删除员工
    public boolean deleteUser(String userId){
      
//一个临时列表
        Collection<DepUserModel> tempList = new ArrayList<DepUserModel>();
      
for(DepUserModel model : depUserList){
          
if(model.getUserId().equals(userId)){
                tempList.add(model);
            }
        }
        depUserList.removeAll(tempList);
      
return true;
    }
}

 

如上,对员工、部门的所有操作都封装在这个中介者类中,还可以添加更多操作。

posted @ 2014-04-24 13:36  Chandler Qian  阅读(1120)  评论(0编辑  收藏  举报