Java 设计模式-中介模式

263 阅读4分钟
  1. 需求分析:
    现在一个电脑销售商店, 需要一个软件来管理商店的经营情况. 该软件可以分为三个部分: 采购管理, 销售管理, 库存管理. 这三个模块是相互依赖关系, 采购模块需要根据电脑的销售情况和库存量来决定采购量, 同时采购量也会导致库存量的变化; 销售模块需要根据库存量来进行销售, 同时在库存量不够的情况下也要依赖采购模块进行新的采购; 库存模块会根据库存量来影响销售的策略, 同时也要影响采购的策略.

    /**
     * 采购管理模块
     */
    public class Purchase {
        // 库存模块
        private Stock stock;
        // 销售模块
        private Sale sale;
        public void buyIBMComputer(int number) {
            // 获取电脑的销售状况
            int saleStatus = sale.getSaleStatus();
            if (saleStatus > 80) { // 销售状况良好
                System.out.println("采购IBM电脑:" + number + "台");
                stock.increase(number);
            } else {
                int buyNumber = number / 2;
                System.out.println("采购IBM电脑:" + buyNumber + "台");
                stock.increase(buyNumber);
            }
        }
        
        public void refuseBuyIBMComputer() {
            System.out.println("不再采购IBM电脑");
        }
        
        public void setStock(Stock stock) {
            this.stock = stock;
        }
        
        public void setSale(Sale sale) {
            this.sale = sale;
        }
    }
    /**
     * 库存管理模块
     */
    public class Stock {
        private int computerNumber = 100;
        // 采购模块
        private Purchase purchase;
        // 销售模块
        private Sale sale;
        /**
         * 增加库存数量
         */ 
        public void increase(int number) {
            this.computerNumber += number;
            System.out.println("库存数量为:" + computerNumber);
        }
        
        /**
         * 减少库存数量
         */
        public void decrease(int number) {
            this.computerNumber -= number;
        }
        
        public int getStockNumber() {
            return this.computerNumber;
        }
        
        /**
         * 存货积压太多, 通知采购不要采购, 通知销售尽快销售
         */
        public void clearStock() {
            System.out.println("清理存货数量为:" + computerNumber);
            sale.offSale();
            purchase.refuseBuyIBM();
        }
    }
    
    /**
     * 销售模块
     */
    public class Sale {
        // 采购模块
        private Purchase purchase;
        // 库存模块
        private Stock stock;
        
        public void saleIBMComputer(int number) {
            if (stock.getStockNumber() < number) {
                purchase.buyIBMComputer(number);
            }
            System.out.println("销售IBM电脑:" + number + "台");
            stock.decrease(number);
        }
        
        public int getSaleStatus() {
            Random rand = new Random(System.currentTimeMillis());
            int saleStatus = rand.nextInt(100);
            System.out.println("IBM电脑销售情况为:" + saleStatus);
            return saleStatus;
        }
        
        public void offSale() {
            System.out.println("折价销售IBM电脑:" + stock.getStockNumber() + "台");
        }
    }
    

    这里每个类都与其它两个类产生了关联关系. 如果模块之间的功能再进行细分, 则会产生更多的依赖. 这些模块无法单独的完成功能, 整个系统表现为一个不可分割的整体, 对某个模块的修改都会对其它模块造成影响. 利用中介者模式可以改变这种依赖.

    public abstract class AbstractMediator {
        protected Purchase purchase;
        protected Sale sale;
        protected Stock stock;
        
        public AbstractMediator() {
        }
        
        public abstract void execute(String str, Object... objects);
    }
    
    public class ConcreteMediator extends AbstractMediator {
        /**
         * 该方法是中介者最重要的方法
         */ 
        public void execute(String str, Object... objects) {
            if ("purchase.buy".equals(str)) { // 采购电脑
                this.buyComputer((Integer)objects[0]);
            } else if ("sale.sell".equals(str)) { // 销售电脑
                this.sellComputer((Integer)objects[0]);
            } else if ("sale.offsell".equals(str)) { // 折价销售
                this.offSell();
            } else if ("stock.clear".equals(str)) { // 清仓处理
                this.clearStock();
            }
        }
        /**
         * 采购电脑-需要依赖其它模块
         */
        private void buyComputer(int number) {
            int saleStatus = super.sale.getSaleStatus();
            if (saleStatus > 80) { // 销售状况良好
                System.out.println("采购IBM电脑:" + number + "台");
                super.stock.increase(number);
            } else {
                int buyNumber = number / 2;
                System.out.println("采购IBM电脑:" + buyNumber + "台");
                super.stock.increase(buyNumber);
            }
        }
        
        /**
         * 销售电脑-需要依赖其它模块
         */
        private void sellComputer(int number) {
            if (super.stock.getStockNumber() < number) {
                super.purchase.buyIBMComputer(number);
            }
            super.stock.decrease(number);
        
        /**
         * 折价销售电脑-需要依赖其它模块
         */
        private void offSell() {
            System.out.println("折价销售IBM电脑:" + super.stock.getStockNumber() + "台");
        }
        
        /**
         * 清仓处理-需要依赖其它模块
         */
        private void clearStock() {
            super.sale.offSale();
            super.purchase.refuseBuyIBM();
        }
    }
    
    public abstract class AbstractColleague {
        protected AbstractMediator mediator;
        
        public AbstractColleague(AbstractMediator mediator) {
            this.mediator = mediator;
        }
    }
    
    public class Purchase extends AbstractColleague {
        public Purchase(AbstractMediator mediator) {
            super(mediator);
        }
        
        /**
         * 需要依赖其它模块的方法则通过中介者来调用
         */
        public void buyIBMComputer(int number) {
            super.mediator.execute("putchase.buy", number);
        }
        
        /**
         * 不需要依赖其它模块的方法则自己实现
         */
        publicvoid refuseBuyIBM() {
            System.out.println("不再采购IBM电脑");
        }
    }
    
    public class Stock extends AbstractColleague {
        private int computerNumber = 100;
        public Stock(AbstractMediator mediator) {
            super(mediator);
        }
        /**
         * 不需要依赖其它模块的方法则自己实现
         */ 
        public void increase(int number) {
            this.computerNumber += number;
            System.out.println("库存数量为:" + computerNumber);
        }
        
        /**
         * 不需要依赖其它模块的方法则自己实现
         */
        public void decrease(int number) {
            this.computerNumber -= number;
        }
        
        public int getStockNumber() {
            return this.computerNumber;
        }
        
        /**
         * 需要依赖其它模块的方法则通过中介者来调用
         */
        public void clearStock() {
            System.out.println("清理存货数量为:" + computerNumber);
            super.mediator.execute("stock.clear");
        }
    }
    
    public class Sale extends AbstractColleague {
        public Sale(AbstractMediator mediator) {
            super(mediator);
        }
        
        /**
         * 需要依赖其它模块的方法则通过中介者来调用
         */
        public void sellIBMComputer(int number) {
            super.mediator.execute("sale.sell", number);
            System.out.println("销售IBM电脑:" + number + "台");
        }
        
        public int getSaleStatus() {
            Random rand = new Random(System.currentTimeMillis());
            int saleStatus = rand.nextInt(100);
            System.out.println("IBM电脑销售情况为:" + saleStatus);
            return saleStatus;
        }
        
        /**
         * 需要依赖其它模块的方法则通过中介者来调用
         */
        public void offSale() {
            super.mediator.execute("sale.offsell");
        }
    }
    

    通过增加中介者来进行模块之间调用关系的管理, 所有需要依赖其它模块实现的功能都通过中介者进行调用. 其实中介者有点类似于计算机网络中的交换机的角色, 整个系统通过中介者形成了一个星型的拓扑结构.

  2. 中介者模式的定义: Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently(用一个中介对象封装一系列的对象 交互, 中介者使各对象不需要显示地相互作用, 从而使其耦合松散, 而且可以独立地改变它 们之间的交互).

    mediator

  3. 中介者模式的应用:
    java.util.concurrent.Executor#execute() 方法
    java.lang.reflect.Method#invoke() 方法

  4. 参考:
    [1] : Java 库中的设计模式
    [2] : 设计模式之禅
    [3] : Head First 设计模式