1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <title></title>
  5     <meta charset="UTF-8"/>
  6 </head>
  7 <body>
  8 <img src="1.jpg" alt=""/>
  9
 10 <script>
 11 /*
 12  设计原则
 13
 14  1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
 15
 16  把会变化的部分取出并“封装”起来,好让其他部分不会受到影响。代码变化引起的不经意后果变少,系统变得更有弹性。
 17
 18  几乎是每个设计模式的精神所在。所有的模式都提供了一套方法让“系统中的某部分改变不会影响其他部分”。
 19
 20
 21  2.针对接口编程,而不是针对实现编程。
 22
 23  针对接口编程真正的意思是“针对超类型(supertype)编程”。
 24  变量的声明类型应该是超类型,通常是一个抽象类或者是一个接口,如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个变量。这也意味着,声明类时不用理会以后执行时的真正对象类型
 25
 26
 27  3.多用组合,少用继承。
 28  。
 29  */
 30
 31 /**
 32  * 策略模式
 33  *
 34  * 定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
 35  *
 36  * 本质:
 37  * 分离算法,选择实现。
 38  *
 39  * 策略模式的重心不是如何实现算法,而是如何组织,调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。
 40  *
 41  * 这里鸭子的行为即是算法族。
 42  *
 43  * 为了实现让算法能独立于使用它的客户,策略模式引入了一个上下文对象,这个对象负责持有算法,但是不负责绝对具体选用哪个算法,把选择算法的功能交给了客户,由客户选择好具体的算法后,设置到上下文对象中,让上下文对象持有客户选择的算法。当客户通知上下文对象执行功能的时候,上下文对象则转调具体的算法。这样一来,具体的算法和直接使用算法的客户是分离的。
 44  * 具体的算法和使用它的客户分离以后,使得算法可独立于使用它的客户而变化,并且能够动态地切换需要使用的算法,只要客户端动态地选择使用不同的算法,然后设置到上下文对象中,在实际调用的时候,就可以调用到不同的算法。
 45  *
 46  * 1.功能
 47  * 策略模式的功能是把具体的算法实现从具体的业务处理中独立出来,把它们实现成为单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换。
 48  * 策略模式的中心不是如何来实现算法,而是如何组织,调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。
 49  *
 50  * 2.策略模式和if-else语句
 51  * 多个if-else语句表达的就是一个平等的功能结构。而策略模式就是把各个平等的具体实现封装到单独的策略实现类了,然后通过上下文来与具体的策略类进行交互。
 52  * 因此多个if-else语句可以考虑使用策略模式。
 53  *
 54  * 3.算法的平等性
 55  * 策略模式的很大的特点就是各个策略算法的平等性。所有策略算法在实现上也是相互独立的,相互之间没有依赖的。
 56  * 所以策略算法是相同行为的不同实现。
 57  *
 58  * 4.谁来选择具体的策略算法
 59  * 一个是在客户端,当使用上下文的时候,由客户端来选择具体的策略算法,然后把这个策略算法设置给上下文。
 60  * 另一个是由上下文来选择具体的策略算法。
 61  *
 62  * 5.运行时策略的唯一性
 63  * 运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但使用时只能使用一个。
 64  *
 65  * 6.增加新的策略
 66  * 策略模式可以让你很灵活地扩展新的算法。
 67  *
 68  *
 69  * 策略模式的调用顺序
 70  * 1.先是客户端来选择并创建具体的策略对象。
 71  * 2.然后客户端创建上下文。
 72  * 3.接下来客户端就可以调用上下文的方法来执行功能了,在调用的时候,从客户端传入算法需要的参数。
 73  * 4.上下文接到客户的调用请求,会把这个转发给它持有的Strategy。
 74  *
 75  *
 76  * Context和Strategy的关系
 77  * 通常是上下文使用具体的策略实现对象,反过来,策略实现对象也可以从山下问获取所需要的数据。
 78  *
 79  *
 80  * 策略模式结合模板方法模式
 81  * 对于一系列算法的实现上存在公共功能的情况,策略模式可以有以下三种实现方式:
 82  * 1.在上下文当中实现公共功能,让所有具体的策略算法回调这些方法。
 83  * 2.将策略的借口改成抽象类,然后在其中实现具体算法的公共功能。
 84  * 3.为所有的策略算法定义一个抽象的父类,让这个父类去实现策略的接口,然后在这个父类中去实现公共的功能。
 85  * 如果这个时候发现一系列算法的实现步骤都是一样的,只是在某些局部步骤上有所不用的情况,那就可以在这个抽象类里面定义算法实现的骨架,然后让具体的策略算法去实现变化的部分。这样的一个结构自然就变成策略模式结合模板方法模式了。那个抽象类就成了模板方法模式的模板类。
 86  */
 87
 88 (function () {
 89     // 示例代码
 90
 91     // 具体算法
 92     function ConcreteStrategyA() {}
 93
 94     ConcreteStrategyA.prototype.algorithmInterface = function () {/*具体算法的实现*/};
 95
 96     function ConcreteStrategyB() {}
 97
 98     ConcreteStrategyB.prototype.algorithmInterface = function () {};
 99
100     function ConcreteStrategyC() {}
101
102     ConcreteStrategyC.prototype.algorithmInterface = function () {};
103
104     // 上下文对象,通常会持有一个具体的策略对象
105     function Context(strategy) {
106         this.strategy = strategy;
107     }
108
109     //上下文对客户端提供的操作接口,可以有参数和返回值
110     Context.prototype.contextInterface = function () {
111         // 转调具体的策略对象进行算法运算
112         this.strategy.algorithmInterface();
113     };
114
115 }());
116
117 (function () {
118     // 容错恢复机制
119     function DbLog() {
120         this.log = function (msg) {
121             if (msg && msg.trim().length > 5) {
122                 fds;  // make mistake
123             }
124             console.log('现在把' + msg + '记录到数据库中');
125         };
126     }
127
128     function FileLog() {
129         this.log = function (msg) {
130             console.log('现在把' + msg + '记录到文件中');
131         };
132     }
133
134     function LogContext() {
135         this.log = function (msg) {
136             var strategy = new DbLog();
137             try {
138                 strategy.log(msg);
139             } catch (e) {
140                 strategy = new FileLog();
141                 strategy.log(msg);
142             }
143         };
144     }
145
146     var log = new LogContext();
147     log.log('"记录日志"');
148     log.log('"再次记录日志"');
149
150 }());
151
152
153 /*
154  适用性
155
156  1.许多相关的类仅仅是行为有异。“策略”提供了一种同多个行为中的一个行为来配置一个类的方法。
157  2.
158  需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。
159  3.算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的,与算法相关的数据结构。
160  4.一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
161  */
162
163 /*
164  优点:
165
166  1.定义了一系列算法。
167  2.避免多重条件语句。
168  3.更好的扩展性。
169
170  缺点:
171
172  1.客户必须了解每种策略的不同。
173  2.增加了对象数目。
174  3.只适合扁平的算法结构。
175  对于出现需要嵌套使用多个算法的情况,可以考虑使用装饰者模式,或是变形的职责链模式。
176
177
178  相关模式
179  策略模式和状态模式
180  从模式结构上看是一样的,但是实现的功能确实不一样的。
181  状态模式是根据状态的变化来选择相应的行为,不同的状态对应不同的类,每个状态对应的类实现了该状态对应的功能,在实现功能的同时,还会维护状态数据的变化。这些实现状态对应的功能的类之间是不能相互替换的。策略模式是根据需要或者是客户端的要求来选择相应的实现类,各个实现类是平等的,是可以相互替换的。
182  另外策略模式可以让客户端来选择需要使用的策略算法;而状态模式一般是上下文,或者是在状态实现类里面来维护具体的状态数据们通常不由客户端来制定状态。
183
184  策略模式和模板方法模式
185  可组合使用。模板方法重在封装算法骨架,而策略模式重在分离并封装算法实现。
186
187  策略模式和享元模式
188  可组合使用。
189
190  */
191
192
193 (function () {
194     // 抽象上下文类
195     var Duck = function (quackBehavior) {
196         this.quackBehavior = quackBehavior;
197     };
198     Duck.prototype = {
199         display: function () {
200             throw new Error('This is abstract method');
201         },
202         performQuack: function () {
203             this.quackBehavior.quack();
204         },
205         swim: function () {
206             console.log('All ducks float, even decoys');
207         }
208     };
209
210     // 具体上下文类
211     var MallardDuck = function () {
212         Duck.apply(this, arguments);
213     };
214     MallardDuck.prototype.__proto__ = Duck.prototype;
215     MallardDuck.prototype.display = function () {
216         console.log('I\'m a real Mallard duck.');
217     };
218
219     // 抽象算法类
220     var QuackBehavior = function () {
221     };
222     QuackBehavior.prototype.quack = function () {
223         throw new Error('this is an interface');
224     };
225
226     // 具体算法类
227     var MuteQuack = function () {
228     };
229     MuteQuack.prototype.__proto__ = QuackBehavior.prototype;
230     MuteQuack.prototype.quack = function () {
231         console.log('slience');
232     };
233
234     // 客户端
235     var MiniDucksSimulator = function () {
236         this.main();
237     };
238     MiniDucksSimulator.prototype = {
239         main: function () {
240             var mallard = new MallardDuck(new MuteQuack());
241             mallard.performQuack();
242         }
243     };
244     new MiniDucksSimulator();
245
246     // 动态设定行为
247     Duck.prototype.setQuackBehavior = function (qb) {
248         this.quackBehavior = qb;
249     };
250
251     var ModelDuck = function () {
252         Duck.apply(this, arguments);
253     };
254     ModelDuck.prototype.__proto__ = Duck.prototype;
255     ModelDuck.prototype.display = function () {
256         console.log('T\'m a model duck.');
257     };
258
259     var QuackSpeakerPowered = function () {
260     };
261     QuackSpeakerPowered.prototype.quack = function () {
262         console.log('I\'m quacking with a speaker');
263     };
264
265     MiniDucksSimulator.prototype.main = function () {
266         var model = new ModelDuck(new MuteQuack());
267         model.performQuack();
268         model.setQuackBehavior(new QuackSpeakerPowered());
269         model.performQuack();
270     };
271     new MiniDucksSimulator();
272
273
274     // 策略,定义计算报价算法的接口
275     var Strategy = function () {
276     };
277     Strategy.prototype.calcPrice = function (goodsPrice) {
278         throw new Error('This is an abstract interface');
279     };
280
281     var NormalCustomerStrategy = function () {
282     };
283     NormalCustomerStrategy.prototype.__proto__ = Strategy.prototype;
284     NormalCustomerStrategy.prototype.calcPrice = function (goodsPrice) {
285         console.log('对于新客户或者普通客户,没有折扣');
286         return goodsPrice;
287     };
288
289     // 具体算法实现
290     var OldCustomerStrategy = function () {
291     };
292     OldCustomerStrategy.prototype.__proto__ = Strategy.prototype;
293     OldCustomerStrategy.prototype.calcPrice = function (goodsPrice) {
294         console.log('对于老客户,统一折扣5%');
295         return goodsPrice * (1 - 0.05);
296     };
297
298     // 价格管理,主要完成计算向客户所报价格的功能
299     var Price = function (strategy) {
300         this.strategy = strategy;
301     };
302     Price.prototype.quote = function (goodsPrice) {
303         return this.strategy.calcPrice(goodsPrice);
304     };
305
306     // 选择并创建需要使用的策略对象
307     var strategy = new OldCustomerStrategy();
308     // 创建上下文
309     var ctx = new Price(strategy);
310     // 计算报价
311     var quote = ctx.quote(1000);
312     console.log('向客户报价:' + quote);
313 }());
314
315
316 (function () {
317     // 表单验证
318     var r_space = /\s+/;
319
320     // HTML转义
321     var ENCODECHAR = {
322         '<': '&lt;',
323         '>': '&gt;',
324         '&': '&amp;',
325         '"': '&quot;'
326     };
327
328     // 验证策略
329     var VALIDTYPES = {
330         'nonEmpty': {
331             validate: function (value) {
332                 return value !== '';
333             },
334             msg: '此项不能为空'
335         },
336         'email': {
337             validate: function (value) {
338                 return (/^[\w\-]+@[\w\-]+(?:\.[\w\-]+)+$/.test(value));
339             },
340             msg: function (value) {
341                 return (value ? '请输入正确格式的邮箱' : '请输入你的邮箱');
342             }
343         },
344         'phone': {
345             validate: function (value) {
346                 return (/^1[3458]\d{9}$/.test(value));
347             },
348             msg: function (value) {
349                 return (value ? '请输入正确格式的手机号码' : '请输入你的手机号码');
350             }
351         }
352     };
353
354     var formHooks = {
355         'radio': 'checked',
356         'checkbox': 'checked'
357     };
358
359     var formEventsHooks = {
360         'text': formEventsGetter('blur'),
361         'textarea': formEventsGetter('blur'),
362         'checkbox': formEventsGetter('click'),
363         'select': formEventsGetter('change'),
364         'radio': formEventsGetter('click')
365     };
366
367     function formEventsGetter(type) {
368         return function (el, context, item) {
369             $(el).on(type, function () {
370                 context.errHandler = [];
371                 parseEachEleCfg(item);
372
373                 validating(item, context.errHandler);
374
375                 context.handleError();
376             });
377         };
378     }
379
380     /**
381      * 验证器构造器
382      * @param {Object} formInstance 用户自定义规则
383      * @constructor
384      */
385     function Validator(formInstance) {
386         var form = formInstance.form;
387         if (!form) return;
388
389         this.form = form;
390
391         /**
392          [{
393             elem:elem,
394             value: '',
395             type: ''
396             [optional] ,checker: {checker: func, description: ''}
397          }, ..]
398          */
399         this.config = [];
400
401         this.callbackLists = {
402             success: [],
403             failure: []
404         };
405
406         /*
407          this.errHandler;
408          */
409
410         if (formInstance.types) $.extend(VALIDTYPES, formInstance.types);
411
412         this.parsed = false;
413         this.isDefaultPrevented = false;
414         this.ajax = typeof formInstance.ajax === 'boolean' ?
415             formInstance.ajax : true;
416
417         if (formInstance.success) this.on('success', formInstance.success);
418         if (formInstance.failure) this.on('failure', formInstance.failure);
419         if (formInstance.beforeSend) this.beforeSend = formInstance.beforeSend;
420
421         if (formInstance.formElementsEvented) {
422             this.parseConfig();
423             this.parsed = true;
424             this.addFormEvents(this.config);
425         }
426
427         var removeClassFn = function (e) {
428             $(e.target).removeClass('processing');
429         };
430         this.on('success', removeClassFn);
431         this.on('failure', removeClassFn);
432
433         this.submit();
434     }
435
436     // 防止XSS
437     Validator.encodeValue = function (value) {
438         for (var i in ENCODECHAR) {
439             if (ENCODECHAR.hasOwnProperty(i))
440                 value = value.replace(new RegExp(i, 'g'), ENCODECHAR[i]);
441         }
442
443         return value;
444     };
445
446     Validator.prototype = {
447         // 为每个表单元素添加事件侦听
448         addFormEvents: function (cfg) {
449             var me = this;
450             var elem, formType, item;
451             for (var i = 0, len = cfg.length; i < len; i++) {
452                 item = cfg[i];
453                 elem = item.elem;
454                 formType = elem.type;
455
456                 formEventsHooks[formType](elem, me, item);
457             }
458         },
459         hasErrors: function () {
460             return !!this.errHandler.length;
461         },
462         on: function (type, cb) {
463             if (!this.callbackLists[type]) {
464                 throw new Error('no matched event type');
465             }
466
467             this.callbackLists[type] = this.callbackLists[type].concat(
468                     Object.prototype.toString.call(cb) === '[object Array]' ?
469                     cb : [cb]
470             );
471         },
472         off: function (type) {
473             if (!this.callbackLists[type]) return;
474
475             delete this.callbackLists[type];
476         },
477         emit: function (type, args) {
478             if (!this.callbackLists[type]) {
479                 throw new Error('no matched event type');
480             }
481
482             var list = this.callbackLists[type];
483
484             if (type === 'failure' && args && args[0] && args[0].preventDefault) {
485                 args[0].preventDefault();
486             }
487
488             for (var i = 0, len = list.length; i < len; i++) {
489                 if (typeof list[i] === 'function' && list[i].apply(this.form, args) === false)
490                     break;
491             }
492         },
493         submit: function () {
494             var me = this;
495
496             if (!this.form) return;
497
498             $(this.form).on('submit', function (e) {
499                 var $this = $(this);
500
501                 if ($this.hasClass('processing')) return;
502
503                 $this.addClass('processing');
504
505                 me.isDefaultPrevented = false;
506                 e._preventDefault = e.preventDefault;
507                 e.preventDefault = function () {
508                     e._preventDefault();
509                     me.isDefaultPrevented = true;
510                 };
511
512                 // 解析配置,parsed为false时,可再次解析
513                 if (!me.parsed) {
514                     me.parseConfig();
515                     me.parsed = true;
516                 }
517
518                 // 验证
519                 me.validate();
520
521                 // 验证有错误
522                 if (me.hasErrors()) {
523                     me.handleError();
524
525                     me.emit('failure', [e]);
526                     return;
527                 }
528
529                 // ajax提交默认阻止表单提交
530                 if (me.ajax) {
531                     e._preventDefault();
532                 }
533
534                 var def;
535                 var form = this;
536
537                 /*
538                  执行me.beforeSend方法,在成功,提交之前执行,
539                  如果返回false就触发失败回调
540                  可以返回deferred对象,进行异步操作
541                  */
542                 if (me.beforeSend && (def = me.beforeSend()) === false) {
543                     K.handyWarn({
544                         msg: me.beforeSend.errorMsg
545                     });
546
547                     me.emit('failure', [e]);
548                     return;
549                 }
550
551                 // 如果是deferred对象,序列执行回调
552                 if (def && (typeof def.pipe === 'function' || typeof def.then === 'function')) {
553                     def = def.pipe || def.then;
554                     // 因为是异步操作,必须阻止默认表单提交,与异步提交表单不同
555                     if (!e.isDefaultPrevented()) e._preventDefault();
556
557                     return def(function () {
558                         me.isDefaultPrevented = false;
559                         me.emit('success', [e]);
560                         // 提交表单
561                         if (!me.isDefaultPrevented && !me.ajax) form.submit();
562                     }, function () {
563                         me.emit('failure', [e]);
564                     });
565                 } else {
566                     me.emit('success', [e]);
567                 }
568             });
569         },
570         validate: function () {
571             /**
572              [{
573                 elem: elem,
574                 msg: ''
575              }, ...]
576              */
577             this.errHandler = [];
578
579             var item;
580
581             // 遍历配置项
582             for (var i = 0, len = this.config.length; i < len; i++) {
583                 item = this.config[i];
584
585                 if (parseEachEleCfg(item) === false) continue;
586
587                 validating(item, this.errHandler);
588             }
589         },
590         // 解析HTML标签中的“data-valid”属性,将有的保存
591         parseConfig: function () {
592             var elems = $('*[data-valid]:not([disabled]):not([readonly])', this.form);
593             var elem, ruler;
594
595             for (var i = 0, len = elems.length; i < len; i++) {
596                 elem = elems[i];
597                 ruler = elem.getAttribute('data-valid');
598
599                 if (ruler)
600                     this.config.push({
601                         elem: elem,
602                         type: ruler
603                     });
604             }
605         },
606         // 处理错误
607         handleError: function () {
608             var errs = this.errHandler;
609
610             if (errs.length) {
611                 var head = errs.shift();
612                 var elem = head.elem;
613
614                 K.handyWarn({
615                     msg: head.msg,
616                     rel: elem,
617                     relPos: 'right'
618                 });
619
620                 if (elem.value) {
621                     elem.select();
622                 } else {
623                     elem.focus();
624                 }
625             }
626         }
627     };
628
629     // 验证值,如果不符则保存到错误队列中
630     function validating(item, errHandler) {
631         var checkers = item.checker;
632         var description, checker, value, args, elem;
633
634         for (var i = 0, len = checkers.length; i < len; i++) {
635             checker = checkers[i].checker;
636             description = checkers[i].description;
637             elem = item.elem;
638
639             value = elem[formHooks[elem.type.toLowerCase()] || 'value'];
640
641             // fix IE用value兼容HTML5的placeholder
642             if (elem.getAttribute('placeholder') === value) {
643                 value = '';
644             }
645
646             if (value && typeof value === 'string') {
647                 value = Validator.encodeValue(value);
648             }
649
650             args = [value].concat(description);
651
652             if (!checker.validate.apply(elem, args)) {
653                 errHandler.push({
654                     elem: elem,
655                     msg: typeof checker.msg === 'function' ? checker.msg.apply(elem, args) : checker.msg
656                 });
657             }
658         }
659
660         elem = null;
661     }
662
663     var r_brackets = /^([\w-]+)(?:\(([^)]+)\)|)$/;
664
665     function parseEachEleCfg(item) {
666         if (!(item.checker && item.checker.length)) {
667             var type, description, checker;
668             var types = item.type && item.type.split(r_space) || [];
669
670             if (!types.length) return false;
671
672             // 单个元素可以有多个checker,以空格分隔,且单个checker可有相应的描述语
673             // “charLen(24)”, 括号里面是描述语,
674             // 描述语用在错误信息中
675             item.checker = [];
676             for (var i = 0, len = types.length; i < len; i++) {
677                 type = types[i].match(r_brackets);
678                 if (!type) continue;
679                 checker = VALIDTYPES[type[1]];
680                 description = type[2] && type[2].split(',') || [];
681
682                 if (!checker) {
683                     __console.error('没有相应的验证规则:' + type);
684                     continue;
685                 }
686
687                 item.checker.push({
688                     checker: checker,
689                     description: description
690                 });
691             }
692         }
693
694         return true;
695     }
696 }());
697 </script>
698 </body>
699 </html>

转载于:https://www.cnblogs.com/webFrontDev/archive/2013/05/26/3100220.html

javascript设计模式-策略模式(Strategy)相关推荐

  1. 设计模式-策略模式(Strategy)-Java

    设计模式-策略模式(Strategy)-Java 目录 文章目录 1.前言 2.示例案例-电影票打折方案 3.策略模式概述 3.1.策略模式定义 3.2.策略模式结构 3.3.策略模式结构图中角色 3 ...

  2. 解读设计模式----策略模式(Strategy Pattern)

    一.模式概述      策略模式(Strategy Pattern)在外形上与状态模式很相似,但在意图上有些不同.其意图是使这些算法可以相互替换,并提供一种方法来选择最合适的算法.       在我应 ...

  3. 设计模式--策略模式(strategy)

    1.策略模式(strategy ['strætədʒi]) 我的理解是:方案候选模式 (反正关键就是有很多的候选,哈哈) 看了很多例子,都是在说鸭子的,那个例子很好,在这里可以看 他们生产鸭子,我们就 ...

  4. 李建忠设计模式——策略模式Strategy

    目录 1.策略模式定义 1.动机 2.模式定义 3.结构 2.实现例子 1.问题描述 2.代码实现 3.要点总结 4.参考 1.策略模式定义 1.动机 软件构建过程中,某些对象使用的算法可能多种多样, ...

  5. 关于设计模式——策略模式-Strategy Pattern

    文章目录 1 策略模式 1.1 模拟鸭子 1.2 设计原则 1.3 整合行为 1.4 模拟鸭子代码的代码 1.5 动态设定行为 1.6 重新查看整体 1.7 继承和组合 1.8 总结 1.9 优劣期间 ...

  6. 趣谈设计模式 | 策略模式(Strategy):你还在使用冗长的if-else吗?

    文章目录 案例:指挥官AI 策略模式 配合工厂模式 总结 完整代码与文档 案例:指挥官AI 案例可能不符合实际逻辑,仅用于表述设计模式的思想,勿介意 假设我们开发了一款类似全面战争的即时战略游戏,为了 ...

  7. 设计模式 – 策略模式(Strategy)

    2019独角兽企业重金招聘Python工程师标准>>> 实例:商店促销 (1)首先考虑用简单工厂模式进行设计 Ø  客户端代码Main.java package com.yilong ...

  8. 设计模式 - 策略模式Strategy

    策略模式(Strategy): 定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. 1 using System; 2 using System.Co ...

  9. 设计模式——策略模式( Strategy Pattern )

    写代码超过千行,自定义类10个以上,往往写着写着就觉的乱,最终决定抽空补习下设计模式方面的知识.本来AS3出了本关于设计模式的书的,国人也翻译了.我同事也早早买了一本,但前些天我借来看了几页,翻译的太 ...

最新文章

  1. 中小企业市场 一些超级IT企业的动向
  2. 简约之美Jodd-http--深入源码理解http协议
  3. python实现RSA算法,对数据进行加密认证
  4. Spark 性能相关参数配置详解-任务调度篇
  5. Hibernate实体对象的生命周期(三种状态详解)
  6. python类与方法与函数_Python 中的函数与类的方法
  7. 让菜鸡讲一讲网络流(isap)
  8. wap2.0技巧篇(转)
  9. pycharm汉化(搜索不到插件的参考第二中方法)
  10. IO编程(对IO是什么的详解)
  11. 基于React实现的【绿色版电子书阅读器】,支持离线下载
  12. 点扩散函数point spread function (PSF)
  13. 计算机共享网络的账号密码怎么设置密码,win10局域网共享怎么设置账号密码
  14. 浏览器 文本转语音播放 Demo [SpeechSynthesis]
  15. Kubeadm初始化Kubernetes集群
  16. 超市管理系统设计报告
  17. .podSpec文件相关知识整理
  18. 多点触摸TP的touch异常事件
  19. 什么是苏黎士投机定律(Zurich Axiom)
  20. 汇编学习之nasm编译器下载使用

热门文章

  1. Cesium源码解读系列(一):GeoJsonDataSource如何处理geojson格式的数据
  2. KALI - 暴破wifi之抓取握手包
  3. Tensorflow笔记(八)——Estimator
  4. cURL error 18: transfer closed with xxxxxxx bytes remaining to read
  5. Xavier 下GMSL相机ROS驱动发布CompressedImage消息(基于NVJPG硬件编码)
  6. 净水行业首家,安吉尔新水效国标检测能力获CNAS认可
  7. 校园二手商城小程序,手把手带你开发一款云开发版商城小程序,校园二手微信小程序,可升级社区团购小程序
  8. PXC 配置笔记-从MySQL直接转成PXC集群
  9. iamp是什么意思计算机网络,IAMP是什么意思
  10. 第四篇 fluter中为应用添加事件和导航