您的位置:首页 > Web前端 > JavaScript

javascript设计模式入门之策略模式

2013-03-02 22:56 253 查看
话说js设计模式有关的书籍有Ross Harmes / Dustin Diaz 的《Javascript设计模式》,Stoyan Stefanov的《JavaScript Patterns》,Addy Osmani的《Learning JavaScript Design Patterns》。

第一本很早就出来了,比较古老,基本上内容就是,js模拟面向对象语言,再把面向对象的设计模式套进来。

话说,设计模式是一种思想,面向对象语言,函数式语言都能以自己的方式演绎。

第二本,第三本就比较实在了,不那么崇拜面向对象了,虽然还是有点面向对象。

设计模式的入门书国人写的《大话设计模式》,很受用。这本书代码用C#演绎。

于是,决定把那本书的代码用javascript语言演绎,且用里面的设计模式思想。

今天就来说说策略模式吧。

原文是写,商场收银软件的实现。正常收费,打折收费,满xx返xx。

符合现实情况。产品人员,动不动跑过来说,有新需求,来来,给哥加个新功能。

面对不断变化和增加的需求,如何使自己的原先代码改动成本更小,这时候设计模式派上用场了。

话说,我实在看不出来策略模式和简单工厂模式有啥区别,因为我觉得它们都是同样的过程产生的模式。

直到,看到,后面,说,用简单工厂模式,客户端要认识两个类;用策略模式和简单工厂模式结合,客户端只认识一个类。

我顿时被雷到了。外焦里嫩了。

我觉得设计模式的表现,就是改写编程语言的默认调用方式。

至于各种模式,所展现的思想,都能以一个过程展示。这就是万变不离其宗吧。

好了,下面代码展示我的策略模式,其中还有函数式写法。

只要脑子里想着一个原则,把重复抽象出来,大重复基于小重复,应该就能写出和设计模式媲美的代码了,嘻嘻:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>策略模式</title>
<script type="text/javascript">
// 打折收费,基于正常收费;满多少返多少收费,基于正常收费;打折收费结合满多少返多少收费,基于你懂的。
// 正常收费
function cash_normal(price_arg,num_arg) {
return price_arg * num_arg;
}
// 打折收费
function cash_rebate(money_arg,rebate_arg){
return money_arg * rebate_arg;
}
// 满xx返xx
function cash_return(money_input_arg,money_condition_arg, money_return_arg){
if(money_input_arg > money_condition_arg){
return money_input_arg - money_return_arg;
}
else{
return money_input_arg;
}
}

//
function cash_normal_rebate(price_arg, num_arg, rebate_arg){
return cash_rebate(cash_normal(price_arg,num_arg),rebate_arg);
}

function cash_normal_rebate_return(price_arg, num_arg, rebate_arg, money_condition_arg, money_return_arg){
return cash_return(cash_normal_rebate(price_arg,num_arg,rebate_arg),money_condition_arg,money_return_arg)
}

var number = 10;
var price = 10;
console.log("打八折:买"+number+"个,"+price+"元的东西"+cash_normal_rebate(number,price,0.8));
console.log("打八折,满50返10元:"+cash_normal_rebate_return(price,number,0.8,50,10));

// 函数式写法
function tao(){
return tao;
}

function cash_normal2(price_arg,num_arg){
return function(handle_func){
var total_money = price_arg * num_arg;
if(handle_func){
return handle_func(total_money);
}
else{
return tao;
}
};
}
function crsh_rebate_factory(rebate_arg){
return function(total_money){
// var total_money = rebate_arg*total_money;
return function(handle_func){
var discount_money = rebate_arg * total_money;
if(handle_func){
return handle_func(discount_money,rebate_arg);
}
else{
return tao;
}
};
};
}

function show_money(total_money,rebate_arg){
return function(handle_func){
console.log("函数式写法,乘以"+rebate_arg+":" + total_money);
if(handle_func){
return handle_func(total_money);
}
else{
return tao;
}
}
}

cash_normal2(10,10)(crsh_rebate_factory(0.8))(show_money)();
</script>
</head>
<body>

</body>
</html>


函数式写法有意思的地方在于,参数是函数,返回的是函数。完成一个任务,只要不断调用函数就行了,是横向。

而主流抽象方法是,大函数,用到小函数的话,得把小函数的参数,放进大函数的参数列表里面。

设计模式里有一个依赖倒转原则,对于,大函数依赖小函数,不是非常认可。无论大函数,还是小函数都要依赖抽象。

什么是抽象?对于面向对象来说,子类实例可以被父类创建。父类就是子类实例的抽象。

当然,更抽象的是,产品经理的需求和文档。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: