策略模式——为不同的客户推荐不同的策略

在小成的工厂扩大生产规模之后,产品的多样性也提高了,但是产能怎么分配是要根据需求的,小成的公司经过市场调研之后结合自己厂的生产情况制定了几个销售策略,现在小成公司的业务员和客户谈生意的时候都会根据不同的客户需求来提出不同的销售策略来满足客户,如果没有合适的就看情况能不能自定义一个销售策略,当工厂的生产情况改变的时候也可以适当地改变销售策略,就像现在的手机话费套餐,毕竟一切解析权都归商家嘛。这样实现的代码就和小成刚刚学习的策略模式代码一样。

介绍

  策略模式的定义是:策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。简单来说就是把多种方法策略分别封装起来,想改动的时候可以在里面改,想增加又新增一个就行了,听起来和工厂模式差不多,但是实际上是有差别的:“工厂”是只会返回一个“产品”给用户,他不会公开里面这个产品的实现过程给用户看,但是策略模式是返回一种“策略”,这样策略如果包含实现一个“产品”的话,是会公开里面的细节给用户的,而且还需要用户去参与这个“产品”的实现。这也是设计模式中创建型模式和行为型模式的区别。

这是策略模式的结构图:

在里面的角色有:
- 环境接口类(ContextInterface):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用
- 抽象策略类(Strategy):定义所有支持的算法的父类,实现了所有算法的共有功能。 Context使用这个接口来调用某ConcreteStrategy定义的算法。
- 具体策略类(ConcreteStrategy)角色:包装了相关的算法或行为。

看下面代码:

package scut.designmodel.StrategyPattern;

//销售部门制定的策略抽象类
abstract class SalesStrategy {
    //把为客户定制的销售策略展示的方法
    public abstract void show();
}

//为A类公司准备的销售策略A
class StrategyA extends SalesStrategy{

    @Override
    public void show() {
        System.out.println("为客户展示销售策略A");
    }
}

//为B类公司准备的销售策略A
class StrategyB extends SalesStrategy{

    @Override
    public void show() {
        System.out.println("为客户展示销售策略B");
    }
}

class StrategyCostomied extends SalesStrategy{

    @Override
    public void show() {
        System.out.println("没有适合此类公司的销售策略,需要自定义策略");
    }
}

//销售员类,用于连接上下文,即把销售策略推荐给客户
class SalesMan{
    private SalesStrategy SalesStrategyImpl;

    //生成销售员实例,这里使用一个简单的工厂模式,让销售员根据传入的参数选择推荐策略
    public SalesMan(String Company) {
        switch (Company) {
            case "A":
                SalesStrategyImpl = new StrategyA();
                break;
            case "B":
                SalesStrategyImpl = new StrategyB();
                break;
            default:
                SalesStrategyImpl = new StrategyCostomied();

        }

    }

    //展示推荐的策略
    public void SalesManShow(){
        SalesStrategyImpl.show();
    }

}

public class StrategyPattern {
    public static void main(String[] args){
        SalesMan mSalesMan ;
        System.out.println("对于A类客户:");
        mSalesMan = new SalesMan("A");
        mSalesMan.SalesManShow();
        System.out.println("对于B类客户:");
        mSalesMan = new SalesMan("B");
        mSalesMan.SalesManShow();
        System.out.println("对于其他类客户:");
        mSalesMan = new SalesMan("其他");
        mSalesMan.SalesManShow();

    }
}

结果:

对于A类客户:
为客户展示销售策略A
对于B类客户:
为客户展示销售策略B
对于其他类客户:
没有适合此类公司的销售策略,需要自定义策略


在代码里面,SalesMan类实现了ContextInterface的功能,通过客户需求选择来决定使用哪一种销售策略。

应用场景

  • 很多相关的类只是在行为上有差异的时候,就可以通过策略模式来进行封装切换。
  • 当需要使用一个算法的不同变体时。
  • 当一个类定义了多种行为并且这些行为在这个类的操作以多个条件语句的形式出现时。

优点

  1. 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
  2. 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。

缺点

  1. 用户必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着 用户必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于 用户知道所有的算法或行为的情况。
  2. 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。有时候可以使用享元模式来减少类的数量,即通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。

参考:

  1. http://blog.csdn.net/tengzhaorong/article/details/6827093
  2. http://www.cnblogs.com/justinw/archive/2007/02/06/641414.html
  3. 《设计模式其实很简单》,刘径舟,张玉华等编著——清华大学出版社,2013.7

你可能感兴趣的:(设计模式笔记)