策略模式 详解

定义

Strategy定义了一系列的算法,并且将每个算法封装来,而且使它们还可以相互替换;策略模式让算法独立于使用它的客户而独立变化;

角色

  • 环境类(Context):用一个ConcreteStrategy对象来配置,维护一个对Strategy对象的引用,可定义一个接口来让Strategy访问它的数据;
  • 抽象策略类(AbstractStrategy):定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法;
  • 具体策略类(ConcreteStrategy): 以Strategy接口实现某具体算法;

从网上找到的类图
enter image description here

适用场景

  • 许多相关的类仅仅是行为有异,“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态的在几种策略中选择一种;
  • 需要在不同情况下使用不同的策略,或者策略还可能在未来用其他方式来实现;
  • 需要对客户隐藏复杂的、与算法相关的数据结构;
  • 一个类定义了多种行为,并且这些行为在这个类中以多个条件语句的形式出现;

例子

比如鸟和鸟类的行为,鸟有很多种,有会飞的,也有不会飞的,有吱吱叫的,也有呱呱叫的等等,这个时候,我们可以将鸟作为Context,也就是环境类,各种不同的鸟类作为具体的ConcreteContext,继承自鸟类,然后将鸟类的行为作为一个鸟类的接口,比如飞的行为,叫的行为,这些行为分别是Strategy,再在这些行为下面包括具体的行为,继承行为,实现行为的接口,也就是ContreteStrategy;


实现代码

var Shipping = function () {
    this.company = "";
};

Shipping.prototype = {
    selectExpress : function(company) {
        this.company = company;
    },

    caculate : function(package) {
        return this.company.caculate(package);
    }
};

var ShunFeng = function () {
    this.caculate = function (package) {
        return 4.5 * package.weight;
    }
};

var ShenTong = function () {
    this.caculate = function (package) {
        return 4.8 * package.weight;
    }
};

var EMS = function () {
    this.caculate = function (package) {
        return 5.0 * package.weight;
    }
};

var log = (function () {
    var log = "";

    return {
        add : function(msg){
            log += msg + "$ \n";
        },
        show : function(){
            console.log(log);
            log = "";
        }
    }
})();

function run()
{
    var package = {weight : 40};

    var sf = new ShunFeng();
    var st = new ShenTong();
    var ems = new EMS();

    var shipping = new Shipping();

    shipping.selectExpress(sf);
    log.add("ShunFeng :" + shipping.caculate(package));
    shipping.selectExpress(st);
    log.add("ShenTong :" + shipping.caculate(package));
    shipping.selectExpress(ems);
    log.add("EMS :" + shipping.caculate(package));

    log.show();
}

run();

其实这就是一个选择快递公司,然后计算价钱的例子;


优缺点

注意的是

  • 客户必须要知道所有的策略类,并且自行决定使用哪一个策略类;
  • Strategy和Context之间的通信开销;因此很可能某些 ConcreteStrategy不会都用到所有通过这个接口传递给它们的信息;简单的 ConcreteStrategy可能不使用其中的任何信息
  • 策略模式会造成很多的策略类,难以管理;
posted @ 2016-11-07 09:55  banananana  阅读(190)  评论(0编辑  收藏  举报