JavaScript中的策略模式用法介绍

一. 策略模式的定义

策略模式的定义:定义了算法家族,分别封装起来,让它们之间可以相互替换。

策略模式的目的是想将算法的使用与实现分离开来。

二. 策略模式的实现

究其本质,策略模式使用委托去解耦使用它们的算法类。

基于策略模式的程序至少由两部分组成:

第一部分是一组 策略类。策略类封装了具体的算法,并负责具体的计算过程。
第二部分是 环境类 Context。Context接受客户请求,并将请求委托给某一个策略类。
例如:

// 定义一组策略类
var strategies = {
    A: function() { // A策略内容... },
    B: function() { // B策略内容... },
    C: function() { // C策略内容... }
};

// 定义Context环境类,维持对策略对象的引用
var context = function(strategy) {
    // 对strategy的一些处理 ... ...

    return strategy;
};

// 实际调用
context( strategies.A() );
context( strategies.B() );
context( strategies.C() );
这样做有几个好处:可以防止使用大条件语句来决定哪些算法用于特定类型的对象,将关注点分离开来,因此降低了客户端的复杂度,同时还可以促进子类化的组成,提高了模块化和可测性。

2.1 实例:使用策略模式实现图片像素操作

var filterRules = {
    // 灰度
    gray: function(imagedata) {
        var imagedata = imagedata || [],
            pixels = imagedata.data,
            pixelsLen = pixels.length;
        for(var i = 0; i < pixelsLen; i++) {
            pixels[i * 4] = 255 - pixels[i * 4]; // 红色
            pixels[i * 4 + 1] = 255 - pixels[i * 4 + 1]; // 绿色
            pixels[i * 4 + 2] = 255 - pixels[i * 4 + 2]; // 蓝色
        }
    },

    // 反转颜色
    invert: function(imagedata) {
        var imagedata = imagedata || [],
            pixels = imagedata.data,
            pixelsLen = pixels.length;
        for(var i = 0; i < pixelsLen; i++) {
            var average = ( pixels[i * 4] + pixels[i * 4 + 1] + pixels[i * 4 + 2] ) / 3;
            pixels[i * 4] = average; // 红色
            pixels[i * 4 + 1] = average; // 绿色
            pixels[i * 4 + 2] = average; // 蓝色
        }
    },

    // 浮雕
    emboss: function(imagedata) {
        var imagedata = imagedata || [],
            pixels = imagedata.data,
            pixelsLen = pixels.length,
            imageWidth = imagedata.width;
        for(var i = 0; i < pixelsLen; i++) {
            if(i < pixelsLen - imageWidth * 4) {
                if((i + 1) % 4 !== 0) {
                    if((i + 4) % (imageWidth * 4) == 0) {
                        pixels[i] = pixels[i - 4];
                        pixels[i + 1] = pixels[i - 3];
                        pixels[i + 2] = pixels[i - 2];
                        pixels[i + 3] = pixels[i - 1];
                        i += 4;
                    } else {
                        pixels[i] = 255 / 2 + 2 * pixels[i] - pixels[i + 4] - pixels[i + imageWidth * 4];
                    }
                }
            } else if((i + 1) % 4 !== 0) {
                pixels[i] = pixels[i - imageWidth * 4];
            }
        }
    }
};
var canvas = document.getElementById("canvas"),
    context = canvas.getContext("2d"),
    image = new Image();

image.src = "1.jpg";
image.onload = function() {
    context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
    // renderFilter(context, filter.gray, canvas);
};

// 渲染滤镜
function renderFilter(context, filter, canvas) {
    var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
    if(filterRules[filter]) {
        filterRules[filter](imageData);
    }
    context.putImageData(imageData, 0, 0);
}

// 选择滤镜模式
var filterBtn = document.getElementById("btn_filter");
filterBtn.addEventListener("click", function(e) {
    var target = e.target,
        filter = target.dataset.filter;
        if(filterRules[filter]) {
            renderFilter(context, filter, canvas);
        }
}, false);

效果如下:

【正在施工中… …】

2.2 实例:使用策略模式实现表单校验

参考《JavaScript设计模式与开发实践》第五章P80~86。

三. 策略模式的优缺点

3.1 策略模式的优点:

策略模式利用组合、委托和多态等技术和思想,可以有效地避免使用多重条件判断;
算法独立封装,使得他们可以自由切换,易于理解和扩展;
复用性高。
3.2 策略模式的缺点:

策略类会增多;
所有策略类都需要对外暴露。

四. 策略模式的适用场景

策略模式的适用场景有:

当系统中有许多类,而他们之间的区别仅在于行为时,那么使用策略模式可以动态地让一个对象在许多行为中选择一种;
当系统需要动态地在几种算法中选择一种时;
一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。

五. 总结

策略模式将算法的使用和算法的实现分离开来,将不变的部分和变化的部分分隔开,从而使程序进行解耦。

策略模式对于可提炼出多种较通用的算法,并在不同的使用场景下按需选择某一种或某几种策略完成对应的业务逻辑比较适用。所以,当业务逻辑涉及到分类和按需应用时,可考虑使用策略模式来实现。

时间: 2024-10-01 10:11:38

JavaScript中的策略模式用法介绍的相关文章

javascript中var声明变量用法介绍

var 语句声明变量. var variable1 [ = value1 ] [, variable2 [ = value2], ...] 参数 variable, variable2 被声明的变量的名字. value, value2 赋给变量的初始化值. 说明 使用 var 语句来声明变量.这些变量可以在声明时或声明后在脚本中被赋值 一个关于var变量的问题 一个朋友问了一个js问题, 一段看不出有任何问题的代码, 在ie下报错:"object doesn't support this pro

javascript 中string.lastIndexOf()函数用法介绍

语法 var index = array.lastIndexOf(searchElement[, fromIndex]); 参数说明 searchElement: 要搜索的元素 fromIndex : 开始搜索的位置,默认为数组的长度(length),在这样的情况下,将搜索所有的数组元素.如果传入的值大于或等于数组的范围(length),将搜索整个数组,如果传入的值小于 0 ,将返回 -1 ,在这样的情况下,搜索操作将不被执行.搜索是反方向进行的. 功能说明 比较 searchElement 和

javascript中match函数的用法小结

 本篇文章主要是对javascript中match函数的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 javascript中的match函数是使用正则表达式对字符串进行查找,并将查找的结果作为数组返回,在实际开发中非常的有用,使用方法如下:  stringObj.match(rgExp)  其中stringObj是必选项.对其进行查找的 String 对象或字符串文字.  rgExp是必选项.为包含正则表达式模式和可用标志的正则表达式对象.也可以是包含正则表达式模式和可

详解JavaScript中循环控制语句的用法

  这篇文章主要介绍了详解JavaScript中循环控制语句的用法,包括break语句和continue语句的使用方法,需要的朋友可以参考下 JavaScript提供完全控制来处理循环和switch语句.可能有一种情况,当你需要退出一个循环,但未达到其底部.也可能有一种情况,当要跳过的码块的一部分,并直接开始下一个迭代. 为了处理这些情况下,JavaScript提供了break和continue语句.这些语句是用来马上退出任何循环或启动循环的下一次迭代. break 语句: break语句,这是

JavaScript中switch语句的用法详解

  这篇文章主要介绍了JavaScript中switch语句的用法详解,是JS入门学习中的基础知识,需要的朋友可以参考下 可以使用多个if... else if语句,如前面的章节,执行多路分支.然而,这并不总是最佳的解决方案,尤其是当所有分支的依赖单一的变量的值. 使用JavaScript1.2开始,你可以用它处理的正是这种情况,使用一个switch语句,它这样做更有效,如果不是反复地使用if... else if语句. 语法 switch语句的基本语法给出一个expression ,以评估计算

JavaScript中的DSL元编程介绍

 这篇文章主要介绍了JavaScript中的DSL元编程介绍,本文讲解了JavaScript元编程.JavaScript eval.JavaScript new Function()等内容,需要的朋友可以参考下     在看JavaScript Template源码的时候,发现有一个很有意思的用法用来生成函数,想到这不就是元编程么? JavaScript 元编程   代码如下: 元编程(Metaprogramming)是指某类计算机程序的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它

JavaScript中return false的用法

这篇文章主要介绍了JavaScript中return false的用法,在大多数情况下,为事件处理函数返回false,可以防止默认的事件行为,需要的朋友可以参考下 在大多数情况下,为事件处理函数返回false,可以防止默认的事件行为. 例如,默认情况下点击一个元素,页面会跳转到该元素href属性指定的页. Return False 就相当于终止符,Return True 就相当于执行符.在js中return false的作用一般是用来取消默认动作的.比如你单击一个链接除了触发你的onclick事

JavaScript中的函数模式详解

 这篇文章主要介绍了JavaScript中的函数模式详解,本文讲解了创建函数的语法.函数表达式.命名函数表达式.函数的声明.函数声明与表达式.函数的提升.即时函数模式等内容,需要的朋友可以参考下     JavaScript设计模式的作用是提高代码的重用性,可读性,使代码更容易的维护和扩展 在javascript中,函数是一类对象,这表示他可以作为参数传递给其他函数:此外,函数还可以提供作用域. 创建函数的语法 命名函数表达式 代码如下: //命名函数表达式 var add = function

设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)

在前段时间呢陆陆续续的更新了一系列关于重构的文章.在重构我们既有的代码时,往往会用到设计模式.在之前重构系列的博客中,我们在重构时用到了"工厂模式"."策略模式"."状态模式"等.当然在重构时,有的地方没有点明使用的是那种设计模式.从今天开始,我们就围绕着设计模式这个主题来讨论一下我们常用的设计模式,当然"GoF"的23种设计模式不会全部涉及到,会介绍一些常见的设计模式.在接下来我们要分享的设计模式这个系列博客中,还是以Swi