java中榨汁机的代码_直播开始:'云榨汁机'诞生记--聊聊JavaScript中的'业务建模'...

闭包是JavaScript中的一个重要特性,在之前的博文中,我们说闭包是一个'看似简单,其实很有内涵'的特性。当我们用JavaScript来实现相对复杂的业务建模时,我们可以如何利用'闭包'这个特性呢?JavaScript中的'原型继承',又可以解决业务建模中的哪些问题呢?今天我们就通过一家'榨汁机工厂'生产设计'榨汁机'的故事,来聊一聊'闭包'和'原型继承'在业务建模中的作用。

现在直播开始:

badc59eaa132ce0ea49ebdbe7278fd87.png

1》 工厂默认选用A型刀头方案制造榨汁机

例子当中我们主要涉及到2个函数:

1.榨汁机的生产工厂(JuiceMachineFactory)。

2.生产榨汁机的方案(createJuiceMachineGuide)。

在JuiceMachineFactory中,通过向createJuiceMachineGuide传入参数,可以获得能生产特定刀头的榨汁机的方法_createJuiceMachine,而通过执行_createJuiceMachine,则可以生产出特定刀头的榨汁机。对外表现出来的逻辑就是:JuiceMachineFactory可以确定生产出来的榨汁机所使用的刀头,并且能够生产榨汁机。

用代码表示如下:

var JuiceMachineFactory = function(){var newFactory ={};var _cutterFn = function(){//榨汁机工厂当前使用的榨汁方法,相当于定义了一个特定的刀头

console.log( '正在使用:A型刀头。');

};//获得一种制造榨汁机的方法

var _createJuiceMachine =createJuiceMachineGuide( _cutterFn );//制造了一台榨汁机

newFactory.createMachine = function(){return_createJuiceMachine();

}returnnewFactory;

};var createJuiceMachineGuide = function( cutterFn ){return function(){var newMachine ={};var _cutterInMachine = cutterFn ; //用传入的'刀头'作为制造榨汁机的原件

newMachine.makeJuice= function(){//开始榨汁

console.log( '##开始榨汁:');//调用传入的私有变量

_cutterInMachine();

}returnnewMachine ;

}

}//先创建唯一的一座工厂:

var factory =JuiceMachineFactory();//现在,我们生产一台榨汁机:

var machine_A =factory.createMachine();//使用这台榨汁机

machine_A.makeJuice( );

运行代码之后输出如下结果:

##开始榨汁:

正在使用:A型刀头。

【分析】

1. 和我们预期的一样,我们通过传入_cutterFn来获得一个'采用刀头A来进行榨汁'的榨汁机制造方案,并且用这个方案制造了一台榨汁机。

2. 在使用新造的这台榨汁机进行榨汁的时候,确实是使用了刀头A的方法。

>> 通俗地讲,工厂制造这台榨汁机时,选用了哪种'制造方案',决定了生产出来的榨汁机的特性。

2》工厂选用了B型刀头方案制造榨汁机

经过一段时间的发展,市场人员反馈说,现在用户都希望使用B型的刀头,我们得修改制造一下制造榨汁机的方案了。但是,从目前来看,我们并没有预留'修改榨汁机刀头'的接口,所以需要调整一下工厂,使它能够方便选择采用哪种刀头方案,调整后的代码如下:

var JuiceMachineFactory = function(){var newFactory ={};var _cutterFn = function(){//榨汁机工厂当前使用的榨汁方法,相当于定义了一个特定的刀头

console.log( '正在使用:A型刀头。');

};//获得一种制造榨汁机的方法

var _createJuiceMachine =createJuiceMachineGuide( _cutterFn );//制造了一台榨汁机

newFactory.createMachine = function(){return_createJuiceMachine();

}//修改新的制造榨汁机的方案

newFactory.setCutterFn = function( new_fn ){

_cutterFn=new_fn ;return true;

}returnnewFactory;

};var createJuiceMachineGuide = function( cutterFn ){return function(){var newMachine ={};var _cutterInMachine = cutterFn ; //用传入的'刀头'作为制造榨汁机的原件

newMachine.makeJuice= function(){//开始榨汁

console.log( '##开始榨汁:');//调用传入的私有变量

_cutterInMachine();

}returnnewMachine ;

}

}//先创建唯一的一座工厂:

var factory =JuiceMachineFactory();//现在,我们生产一台榨汁机:

var machine_A =factory.createMachine();//使用这台榨汁机

machine_A.makeJuice( );//设置一下工厂的制造方案

factory.setCutterFn( function(){

console.log('正在使用:B型刀头。');

});//用新的方案再制造一台榨汁机

var machine_B =factory.createMachine();

machine_B.makeJuice( );

运行代码之后输出如下结果:

##开始榨汁:

正在使用:A型刀头。

##开始榨汁:

正在使用:A型刀头。

【分析】

1. 采用默认的工艺,制造出来的榨汁机,采用的是 A型刀头。

2. 后面通过setCutterFn( ) 调整了制造方案,生产出来的榨汁机,按理,应该是采用“B型刀头”了啊!为什么还是A型刀头?!

这个问题引出了JavaScript的一个知识点:JavaScript中的对象的赋值,是一种'引用'传递。

我们分析一下整个过程。

1. 下面的这段代码执行之后,变量_cutterFn引用了一个'函数对象',我们给这个函数对象一个编号:F_007。

var _cutterFn = function(){//榨汁机工厂当前使用的榨汁方法,相当于定义了一个特定的刀头

console.log( '正在使用:A型刀头。');

};

示意图如下:

fa22ee2b027d981b4794f94cfb4a1f6a.png

2.  执行下面的这段代码之后,相当于变量_cutterFn 和 _cutterInMachine 都指向了 F007 这个函数对象。

var _createJuiceMachine = createJuiceMachineGuide( _cutterFn );

示意图如下:

0355b9a17d417bb4233bed0baa018280.png

3. 当我们向用新的方案来制造B型刀头榨汁机,在前面的代码中,我们用了setMakeMachineMethod方法,代码如下:

//设置一下工厂的制造方案

factory.setMakeMachineMethod( function(){

console.log('正在使用:B型刀头。');

});

此时各个变量所指的对象如下所示:

d3486e02de1d2593de591e3b1162f66f.png

因为只是赋值仅仅是变量之间的'引用'传递,所以,执行完毕之后,变量_cutterFn 和 _cutterInMachine 并没有必然的联系!也就是说,_cutterFn 指向了别的地方(代号为F008的新对象),_cutterInMachine 并不会随之改变,除非再来一次赋值。

在我们的例子,我们要改变的其实不是_cutterFn所指的对象,我们应该改变 _cutterInMachine 所指的对象。也就是要重新'赋一次'值,生成一个新的方案_createJuiceMachine。调整后的代码如下:

var JuiceMachineFactory = function(){var newFactory ={};var _cutterFn = function(){

console.log('正在使用:A型刀头。');

};//获得一种制造榨汁机的方法

var _createJuiceMachine =createJuiceMachineGuide( _cutterFn );//制造了一台榨汁机

newFactory.createMachine = function(){return_createJuiceMachine();

}//修改新的制造榨汁机的方案

newFactory.setMakeMachineMethod = function( new_fn ){

_cutterFn=new_fn ;//关键是修改下面的内容

_createJuiceMachine =createJuiceMachineGuide( _cutterFn );return true;

}returnnewFactory;

};var createJuiceMachineGuide = function( cutterFn ){return function(){var newMachine ={};var _cutterInMachine = cutterFn ; //用传入的'刀头'作为制造榨汁机的原件

newMachine.makeJuice= function(){//开始榨汁

console.log( '##开始榨汁:');//调用传入的私有变量

_cutterInMachine();

}returnnewMachine ;

}

}//先创建唯一的一座工厂:

var factory =JuiceMachineFactory();//现在,我们生产一台榨汁机:

var machine_A =factory.createMachine();//使用这台榨汁机

machine_A.makeJuice( );//设置一下工厂的制造方案

factory.setMakeMachineMethod( function(){

console.log('正在使用:B型刀头。');

});//用新的方案再制造一台榨汁机

var machine_B =factory.createMachine();

machine_B.makeJuice( );//再看一下原来制造的那台machine_A,是否还是使用了A型刀头?//答案是还是A型刀头,因为每执行一次createJuiceMachineGuide,其实是新增一个闭包!//也就是说,//制造machine_A的那套方案,并没有消失,它的榨汁的方法,还是指向F007那个函数对象。//而制造machine_B的那套方案,榨汁方法指向了F008这个函数对象。

machine_A.makeJuice( );

运行代码之后输出如下结果:

##开始榨汁:

正在使用:A型刀头。

##开始榨汁:

正在使用:B型刀头。

##开始榨汁:

正在使用:A型刀头。

这回就正确了!

在生成对象machine_A和machine_B的时候,实际上我们调用了两次createJuiceMachineGuide,生成了两个独立的'运行时环境',而在这两次调用的过程中,运行时环境中的_cutterInMachine私有变量所指向的对象是不一样的。

整个过程示意如下:

24ed059d616a922e46ccc3fb6d6640b3.png

【小节】

1. JavaScript中的赋值、参数传递都是'引用'传递。

"这个好理解不?",

"好理解。"

2. 执行一次'闭包'函数,会生成一个独立的'运行时环境'。

"这个好理解不?"

"好理解哈,相当于返回一个对象,这个对象中的函数可以访问'闭包'函数中的私有成员。"

把它们放到一起综合起来理解,就可以很好的解释"工厂可以决定生产出来的榨汁机采用哪种'刀头'了。"

2》给榨汁机添加'水果'

截止目前为止,我们在'榨汁机'这个模型中,其实还仅仅定义了'榨汁方法',并且确定,采用哪种榨汁方法(选用哪种刀头),是在工厂设置'制造方案'是决定的。但是,完整的榨汁过程,应该是有'水果'的,并且,'水果'应该是可以替换的。

用代码描述如下:

var JuiceMachineFactory = function(){var newFactory ={};var _cutterFn = function(){

console.log('正在使用:A型刀头。');

};//获得一种制造榨汁机的方法

var _createJuiceMachine =createJuiceMachineGuide( _cutterFn );//制造了一台榨汁机

newFactory.createMachine = function(){return_createJuiceMachine();

}//修改新的制造榨汁机的方案

newFactory.setMakeMachineMethod = function( new_fn ){

_cutterFn=new_fn ;//关键是修改下面的内容

_createJuiceMachine =createJuiceMachineGuide( _cutterFn );return true;

}returnnewFactory;

};var createJuiceMachineGuide = function( cutterFn ){return function(){var newMachine ={};var _cutterInMachine = cutterFn ; //用传入的'刀头'作为制造榨汁机的原件

var _fruit = '橙子' ; //默认是橙子汁

newMachine.selectFruit= function( new_fruit ){

_fruit=new_fruit ;

}

newMachine.makeJuice= function( ){//开始榨汁

console.log( '##开始榨汁:');

console.log('使用水果');//调用传入的私有变量

_cutterInMachine();

}returnnewMachine ;

}

}//先创建唯一的一座工厂:

var factory =JuiceMachineFactory();//现在,我们生产一台榨汁机:

var machine_A =factory.createMachine();//使用这台榨汁机

machine_A.makeJuice( );//选择另外的水果

machine_A.selectFruit( '西瓜');//再次榨水果

machine_A.makeJuice( );

运行代码之后输出如下结果:

##开始榨汁:

使用水果正在使用:A型刀头。

##开始榨汁:

使用水果正在使用:A型刀头。

【分析】

与我们预期的一样:默认情况下,我们使用来榨果汁,因为我们也开放了操纵_fruit的接口,所以,我们也可以使用来榨果汁。

【小节】

到目前为止,我们掌握了以下两个情况的处理:

1. 在工厂中可以根据需要调整制造方案:

我们通过传入参数的方式,结合闭包的特性,更换_createJuiceMachine的值,用另外一个'闭包'的运行结果代替之前的'闭包运行结果'。

由于两个运行结果中的_cutterInMachine的值不同,相当于产生了两套不同的制造榨汁机的方法。

>>

回到举例的场景中:制造榨汁机的工厂,可以决定生产出来的榨汁机采用哪种'刀头'。

对于JavaScript本身,由于'高阶函数'的特点,相当于通过传入参数,可以定制'闭包'函数本身。

举例中:

createJuiceMachineGuide:制造'闭包'函数的函数。

_createJuiceMachine:就是执行createJuiceMachineGuide之后返回的'闭包'函数。

var machine_A = factory.createMachine();:machine_A,执行_createJuiceMachine之后的返回的一个'闭包'。

相关知识点:闭包,高阶函数特性,JavaScript赋值操作的本质。

2. 在榨汁时,可以设定榨汁采用的'水果'。

这相当于给了我们一个从'业务模型'认识'闭包'函数的好例子:

a. 运行'闭包'函数,会产生一个'对象'(或函数定义)。这个'对象'中,原来定义在'闭包'函数中的局部变量和参数,成为这个'对象'的私有成员。而这个'对象'中的方法,则成为'对象'的对外接口(公共函数),这些对外接口可以访问'对象'的私有成员。当然,一般不会在返回的'对象'中直接设置'属性'成员,因为那样是'违背'封装性的原则的。

b. 设计一个'闭包'函数的时候:

1> 如果某个成员是业务对象的属性(例如:_fruit),那么,就把它声明为'闭包'函数的局部变量或通过参数传入。

2> 如果某个函数并不想开放给别人使用(例如:_cutterInMachine),那么也把它声明为'闭包'函数的局部变量或通过参数传入。

3> 业务对象对外呈现出来的功能(例如:makeJuice),则把它声明为该对象的'成员'函数。

4> '闭包'函数中的'私有成员',可以通过对外开放出来的公共函数(makeJuice和selectFruit)更改。

讨论到这里,借助'闭包'和'高阶函数'的特性,我们似乎已经能够实现应用中的'业务'建模。我们定义好一个'闭包函数'之后,就可以'产生满足我们业务要求'的对象,并且,这些对象具有很好的'封装性'。

到现在为止,我们还没有用到this,没有this的日子,似乎也是很美好的。

3》给榨汁机增加云端系统

现在的社会,当我们讲到家电设备时,我们往往会说‘智能家电’,取名称时喜欢带一个'云'字,例如:云冰箱,云电视。其实质就是,每个家电背后都有一个'云端'系统,通过'云端'系统,我们可以'远程'与我们的家电通信。比如,还没有下班,我们知道今天下午有一场AC米兰的球赛。这时候,借助'云端'系统,我们可以通过手机遥控家里的'云电视',让它把AC米兰的球赛先录下来,这样,我们下班回到家就可以观看。

现在,我们要给榨汁机也增加这样的'云端'系统,这样,我们就可以在下班回家的路上远程操控榨汁机,一回到家,就能喝到'新鲜'的果汁。比起那些只有'定时'功能的家电,'云家电'还是要方便很多,比如:你如果发现路上堵车了,就可以晚点启动'榨汁作业'。如果老板告诉你晚上要加一下班,你就可以不启动'榨汁作业'。

好了,现在我们就给榨汁机增加一个'云控制系统',然后增加一个'远程启动'的功能。

var JuiceMachineFactory = function(){var newFactory ={};var _cutterFn = function(){

console.log('正在使用:A型刀头。');

};//获得一种制造榨汁机的方法

var _createJuiceMachine =createJuiceMachineGuide( _cutterFn );//制造了一台榨汁机

newFactory.createMachine = function(){return_createJuiceMachine();

}//修改新的制造榨汁机的方案

newFactory.setMakeMachineMethod = function( new_fn ){

_cutterFn=new_fn ;//关键是修改下面的内容

_createJuiceMachine =createJuiceMachineGuide( _cutterFn );return true;

}returnnewFactory;

};var createJuiceMachineGuide = function( cutterFn ){return function(){var newMachine ={};var _cutterInMachine = cutterFn ; //用传入的'刀头'作为制造榨汁机的原件

var _fruit = '橙子' ; //默认是橙子汁

var _cloudCenter ={

remoteStart:function(){//这里模拟执行远程启动时,云端控制'榨汁机'开始榨汁

console.log( '^^云中心收到指令,马上控制榨汁机开始榨汁^^');

newMachine.makeJuice();return;

}

}

newMachine.selectFruit= function( new_fruit ){

_fruit=new_fruit ;

}

newMachine.makeJuice= function( ){//开始榨汁

console.log( '##开始榨汁:');

console.log('使用水果');//调用传入的私有变量

_cutterInMachine();

}//增加远程启动榨汁机的功能

newMachine.remoteStart = function(){//模拟这个功能要借助云端中心执行

_cloudCenter.remoteStart();

}returnnewMachine ;

}

}//先创建唯一的一座工厂:

var factory =JuiceMachineFactory();//现在,我们生产一台榨汁机:

var machine_A =factory.createMachine();//使用这台榨汁机

machine_A.remoteStart( );

运行代码之后输出如下结果:

^^云中心收到指令,马上控制榨汁机开始榨汁^^##开始榨汁:

使用水果正在使用:A型刀头。

【分析】

嘿嘿,看来增加一个云端的系统也是很简单的嘛。没错,这样的设计目前来看是符合我们的预期的。但是,我们是一个'榨汁机'的工厂,这就意味着我们不是'仅仅'生产一台'榨汁机',我们可能会生产上千台,上万台这样的榨汁机。这样,我们再次从'空间'分配的角度来剖析整个榨汁机的过程。

运行下面的代码:

var machine_A = factory.createMachine();

相当于执行了_createJuiceMachine这样的闭包函数,我们知道:"每执行一次'闭包'函数,JavaScript引擎会为闭包函数中的'局部变量'分配一次空间。"

执行1次'闭包'函数factory.createMachine()之后和执行n次'闭包'函数之后的花费空间示意:

40f51ccdf89df85791669317935e84e4.png

假设_cloudCenter这个局部变量占据了很大的空间,我们用深颜色标识出来。回到业务场景,搭建一个'云中心'需要大量的资金投入,但是,我们现在的搞法就相当于:

"为生产出来的每一台榨汁机,都搭建一个专属的云中心。"

显然,这是不合理的。

有同学可能会说,对于_cloudCenter这个局部变量,我们没有必要在'闭包'函数的函数体内专门全新生成一个对象,可以引用'外部'的一个唯一对象,这样就可以节省大量的空间。

这种方式确实也是一种解决方案,在之前的'地址选择控件开发'这篇博文中,针对全国地址信息模型这个比较大的对象,我们就是采用这种方式。

我们再仔细审视一下_createJuiceMachine这个闭包函数,除了_fruit之外,似乎其他的方法也都很_cloudCenter一样,没有必要每生成一个对象,就全新打造一份!

综合上面的分析,我们可以使用JavaScript的'原型继承'特性,来完成我们的业务目标。

我们先来看一下,优化之前,machine_A, machine_B......这些对象的'原型链'关系。

f2cdaf19665a5b745741dcb7a31613b6.png

如果基于'原型继承'来实现我们的业务目标,那么,我们希望我们的'原型链'关系会变成如下所示:

cf9ec1417f147b9a62d52e86ea4ee28b.png

有一个BaseMachine,具有我们'期望'的功能。新创建的machine_A, machine_B都'原型继承'自BaseMachine。

下面,我们用代码来实现这样的业务:

var JuiceMachineFactory = function(){var newFactory ={};var _cutterFn = function(){

console.log('正在使用:A型刀头。');

};//获得一种制造榨汁机的方法

var _createJuiceMachine =createJuiceMachineGuide( _cutterFn );//先制造一个'原型对象'

var _base_machine =_createJuiceMachine();//制造了一台榨汁机

newFactory.createMachine = function(){//基于'原型'对象来创建新的榨汁机

var new_machine =Object.create( _base_machine );

new_machine.setDefaultFruit();returnnew_machine;

}returnnewFactory;

};var createJuiceMachineGuide = function( cutterFn ){return function(){var newMachine ={};var _cutterInMachine = cutterFn ; //用传入的'刀头'作为制造榨汁机的原件

var _fruit = '橙子' ; //默认是橙子汁

var _cloudCenter ={

remoteStart:function(){//这里模拟执行远程启动时,云端控制'榨汁机'开始榨汁

console.log( '^^云中心收到指令,马上控制榨汁机开始榨汁^^');//注意:因为在makeJuice中使用了this.fruit,

//所以,这里也要用this来调用,否则,makeJuice中的this所指对象就不正确!

this.makeJuice();return;

}

}

newMachine.selectFruit= function( new_fruit ){this.fruit =new_fruit ;

}//看一下当前使用的苹果

newMachine.showFruit = function( ){

console.log('>>正在使用的水果是:' + this.fruit );return;

}

newMachine.setDefaultFruit= function(){this.fruit = _fruit; //设置新的对象使用默认的水果

}

newMachine.makeJuice= function( ){//开始榨汁

console.log( '##开始榨汁:');

console.log('使用水果');//调用传入的私有变量

_cutterInMachine();

}//增加远程启动榨汁机的功能

newMachine.remoteStart = function(){//模拟这个功能要'借助'云端中心执行

//相当于要'借用'_cloudCenter.remoteStart这个函数,借用函数怎么搞,用apply哈

_cloudCenter.remoteStart.apply( this, arguments );

}returnnewMachine ;

}

}//先创建唯一的一座工厂:

var factory =JuiceMachineFactory();//现在,我们生产一台榨汁机:

var machine_A =factory.createMachine();//设置一下水果的值

machine_A.selectFruit( '苹果');//查看一下当前所使用的水果

machine_A.showFruit( );//使用这台榨汁机

machine_A.remoteStart( );//再全新生成一个对象machine_B//var machine_B =factory.createMachine();

machine_B.makeJuice( );

运行代码之后输出如下结果:

>>正在使用的水果是:苹果^^云中心收到指令,马上控制榨汁机开始榨汁^^##开始榨汁:

使用水果正在使用:A型刀头。

##开始榨汁:

使用水果正在使用:A型刀头。

【分析】

就是为了使用'原型继承'这个特性,我们引入了this,为了达到各种预期的效果,我们对各个函数都进行了调整。

1. 工厂中,生成machine对象的方式,调整成:先生成一个原型对象(_base_machine),然后基于这个原型对象创建全新的对象。

2. 基于原型对象创建的全新对象,自己是没有任何'成员属性'的。

所以,我们通过调用new_machine.setDefaultFruit();来为新创建的对象添加自己的成员属性fruit,而它的值就是原型对象(_base_machine)中闭包空间中的值_fruit,这样符合我们的业务预期。

3. 将原型对象中,对外公开方法中_fruit的地方,都换成了this.fruit,因为我们希望,当我们使用原型对象_base_machine中的对外公开方法时,其中的fruit应该指代全新创建的对象的fruit成员,而不是生成_base_machine时,闭包中存在的_fruit。

4. 原型对象的对外公开方法(remoteStart),其实调用的不是原型对象本身拥有的方法,而是'借用'了'第三方对象'_cloudCenter中的方法。如果不做调整,直接调用_cloudCenter.remoteStart();那么,函数体的所指代的this就会指向了_cloudCenter。如何向别的对象'借用'方法,我们在前面的博客'闲聊JS中的apply和call'中有比较详细的介绍,所以,我们采用如下的方式调用:

_cloudCenter.remoteStart.apply( this , arguments );

这样,就确保了当你执行new_machine.remoteStart()时,_cloudCenter.remoteStart函数体中的this也是指代new_machine,与我们的业务预期相符。

经过一番周折,我们终于利用JavaScript的'原型继承'特性,实现了我们的'业务目标'。JavaScript的函数调用特性,使得JavaScript更具有'弹性',当然,也使实现逻辑变得更加复杂。当你'迫不得已'要在函数体中使用this的时候,你一定要想清楚,到时候真正调用这个函数的对象会是谁,它具有什么样的成员属性。

回顾整个过程,下面这个语句,其实是用到了一定的随意性,或者说是JavaScript语言的'弹性'。

newMachine.setDefaultFruit = function(){this.fruit = _fruit; //设置新的对象使用默认的水果

}

如果不存在,那么就给对象新增一个fruit成员属性。不过问题不大,我们把这个随意性控制在selectFruit这个方法当中了。现在再回到第2个场景"工厂选用了B型刀头方案制造榨汁机",因为我们使用了'原型继承',要换一种榨汁方式,就需要修改原型对象中'运行时环境'中的_cutterInMachine变量。到底要如何修改呢?就留作练习吧。

【总结】

今天我们以'榨汁机工厂'生产特定功能的'榨汁机'为场景,讲解了如何用JavaScript的'闭包'特性进行'业务建模'。首先我们采用了更改'_createJuiceMachine'的方式达到更换榨汁方式的目的。后来,我们给生产的'榨汁机'增加了'云'功能。当增加了'云'功能之后,发现从'空间利用'的角度看,原来的生产'榨汁机'的方式存在一些问题。最后,我们利用了JavaScript的'原型继承'特性,解决了'空间利用'问题。'榨汁机'只是我们讲故事的道具,真正想表达的是JavaScript的各种特性。

下次如果有时间,我们一起聊聊JavaScript社区中的设计模式。这里先举一个小故事。

有一天,老板对小明说,“小明啊,周末我们超市苹果打特价,6.98一斤,你画一张海报宣传一下。”于是,小明设计了下面的一张海报:

ea3b2c06c94b1e0c247202448ff681f6.png

老板说,“设计得不错,果然身手不凡哈!这样,你再画1000份,明天周五给你放一天假,你去东门路口把画好的1000份宣传单发了。”

"再画1000份?!"

现在已经是周四下午5点,你觉得小明是会拿起画笔赶紧开始画呢?还是拿起画笔赶紧开始画呢?当然不会啦,小明肯定会选择拿着之前画好的宣传海报,去扫描复印1000份。

生活中会遇到许多的'迫不得已',所以,我们要学会聪明做事,善待自己。只有聪明地做事,才能使用户满意,老板开心,自己也不闹心。而对于我们写代码的人来说,了解一些'设计模式',也许能使自己做到:聪明地做事情,优雅地写代码,从容面对各种'迫不得已'。

感谢诸位捧场,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值