引用:(23条消息) 《Javascript设计模式与开发实践》关于设计模式典型代码的整理(下):模板方法模式、享元模式、职责链模式、中介者模式、装饰模式、状态模式、适配器模式_QQsilhonette的博客-CSDN博客

8、模板方法模式:一种基于继承的设计模式。

// 模板方法模式
var Beverage = function (param) {

var boilWater = function () {
console.log('把水煮沸');
};

var brew = param.brew || function () {
throw new Error('必须传递brew方法');
};

var pourInCup = param.pourInCup || function () {
throw new Error( '必须传递 pourInCup 方法' );
};
var addCondiments = param.addCondiments || function () {
throw new Error( '必须传递 addCondiments 方法' );
};

var F = function(){};
F.prototype.init = function(){ boilWater();
brew();
pourInCup();
addCondiments();
};
return F;
};

var Coffee = Beverage({ brew: function(){
console.log( '用沸水冲泡咖啡' ); },
pourInCup: function(){
console.log( '把咖啡倒进杯子' );
},
addCondiments: function(){
console.log( '加糖和牛奶' ); }
});

var Tea = Beverage({
brew: function(){
console.log( '用沸水浸泡茶叶' ); },
pourInCup: function(){
console.log( '把茶倒进杯子' );
},
addCondiments: function(){
console.log( '加柠檬' );
}
});
// 测试
var coffee = new Coffee();
coffee.init();

var tea = new Tea();
tea.init();
9、享元模式:运用共享技术来有效支持大量细粒度的对象。

内部状态与外部状态:
 内部状态存储于对象内部。
 内部状态可以被一些对象共享。
 内部状态独立于具体的场景,通常不会改变。
 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享。

// 享元模式
var Model = function (sex) {
this.sex = sex; // 性别为内部状态
};

Model.prototype.takePhoto = function () {
console.log('sex=' + this.sex + ' underwear=' + this.underwear); // 内衣为外部状态
};
// 测试
var maleModel = new Model('male');
femaleModel = new Model('female');

for (var i = 1; i <= 50; i++) {
maleModel.underwear = 'underwear' + i;
maleModel.takePhoto();
};

for ( var j = 1; j <= 50; j++ ){
femaleModel.underwear = 'underwear' + j;
femaleModel.takePhoto();
};

10、职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

// 职责链模式
var order500 = function( orderType, pay, stock ){
if ( orderType === 1 && pay === true ){
console.log( '500 元定金预购,得到 100 优惠券' );
}else{
return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递
}
};

var order200 = function( orderType, pay, stock ){
if ( orderType === 2 && pay === true ){
console.log( '200 元定金预购,得到 50 优惠券' );
}else{
return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递
}
};

var orderNormal = function( orderType, pay, stock ){
if ( stock > 0 ){
console.log( '普通购买,无优惠券' );
}else{
console.log( '手机库存不足' );
}
};
// Chain.prototype.setNextSuccessor 指定在链中的下一个节点
// Chain.prototype.passRequest 传递请求给某个节点
var Chain = function (fn) {
this.fn = fn;
this.successor = null;
};

Chain.prototype.setNextSuccessor = function (successor) {
return this.successor = successor;
};

Chain.prototype.passRequest = function () {
var ret = this.fn.apply(this, arguments);

if(ret === 'nextSuccessor') {
return this.successor && this.successor.passRequest.apply(this.successor, arguments);
}

return ret;
};
// 测试
var chainOrder500 = new Chain( order500 );
var chainOrder200 = new Chain( order200 );
var chainOrderNormal = new Chain( orderNormal );

chainOrder500.setNextSuccessor( chainOrder200 );
chainOrder200.setNextSuccessor( chainOrderNormal);

chainOrder500.passRequest( 1, true, 500 );
chainOrder500.passRequest( 2, true, 500 );
chainOrder500.passRequest( 3, true, 500 );
chainOrder500.passRequest( 1, false, 0 );

11、中介者模式:增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介者对象即可。

// 中介者模式
var goods = { // 手机库存
"red|32G": 3,
"red|16G": 0,
"blue|32G": 1,
"blue|16G": 6
};

var mediator = (function(){
var colorSelect = document.getElementById( 'colorSelect' ),
memorySelect = document.getElementById( 'memorySelect' ),
numberInput = document.getElementById( 'numberInput' ),
colorInfo = document.getElementById( 'colorInfo' ),
memoryInfo = document.getElementById( 'memoryInfo' ),
numberInfo = document.getElementById( 'numberInfo' ),
nextBtn = document.getElementById( 'nextBtn' );
return {
changed: function( obj ){
var color = colorSelect.value, // 颜色
memory = memorySelect.value,// 内存
number = numberInput.value, // 数量
stock = goods[ color + '|' + memory ]; // 颜色和内存对应的手机库存数量
if ( obj === colorSelect ){ // 如果改变的是选择颜色下拉框
colorInfo.innerHTML = color;
}else if ( obj === memorySelect ){
memoryInfo.innerHTML = memory;
}else if ( obj === numberInput ){
numberInfo.innerHTML = number;
}
if ( !color ){
nextBtn.disabled = true; nextBtn.innerHTML = '请选择手机颜色'; return;
}
if ( !memory ){
nextBtn.disabled = true; nextBtn.innerHTML = '请选择内存大小'; return;
}
if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 输入购买数量是否为正整数
nextBtn.disabled = true;
nextBtn.innerHTML = '请输入正确的购买数量'; return;
}
nextBtn.disabled = false;
nextBtn.innerHTML = '放入购物车';
}
}
})();

// 事件函数:
colorSelect.onchange = function(){
mediator.changed( this );
};
memorySelect.onchange = function(){
mediator.changed( this );
};
numberInput.oninput = function(){
mediator.changed( this );
};

12、装饰者模式:在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。

装饰者模式和代理模式:装饰者模式是实实在在的为对象增加新的职责和行为,而代理做的事情还是跟本体 一样。
// 用AOP装饰模式
Function.prototype.before = function(beforefn) {
var _self = this; // 保存原函数的引用
return function () {
beforefn.apply(this, arguments);
return _self.apply(this, arguments);
}
}

Function.prototype.after = function (afterfn) {
var _self = this;
return function () {
var ret = _self.apply(this, arguments);
afterfn.apply(this, arguments);
return ret;
}
}

13、状态模式:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

// 状态模式
var delegate = function (client, delegation) {
return {
buttonWasPressed: function () {
return delegation.buttonWasPressed.apply(client, arguments);
}
}
};

var FSM = {
off: {
buttonWasPressed: function() {
console.log('关灯');
this.button.innerHTML = '下一次按我是开灯';
this.currState = this.onState;
}
},
on: {
buttonWasPressed: function(){
console.log( '开灯' );
this.button.innerHTML = '下一次按我是关灯';
this.currState = this.offState;
}
}
};

var Light = function () {
this.offState = delegate(this, FSM.off);
this.onState = delegate(this, FSM.on);
this.currState = this.offState;
this.button = null;
};

Light.prototype.init = function () {
var button = document.createElement('button');
self = this;
button.innerHTML = '已关灯';
this.button = document.body.appendChild(button);
this.button.onclick = function () {
self.currState.buttonWasPressed();
}
};
// 测试
var light = new Light();
light.init();

14、适配器模式:解决两个软件实体间的接口不兼容的问题。

// 适配器模式
var renderMap = function( map ){
if ( map.show instanceof Function ){
map.show();
}
};

var googleMap = {
show: function(){
console.log( '开始渲染谷歌地图' );
}
};
var baiduMap = {
display: function(){
console.log( '开始渲染百度地图' );
}
};
var baiduMapAdapter = {
show: function(){
return baiduMap.display();
}
};
renderMap( googleMap ); // 输出:开始渲染谷歌地图
renderMap( baiduMapAdapter ); // 输出:开始渲染百度地图

QQsilhonette
关注
————————————————
版权声明:本文为CSDN博主「QQsilhonette」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/QQsilhonette/article/details/84954376

js设计模式(下)的更多相关文章

  1. JS设计模式(一)

    刚入职时,看过一段时间的设计模式,似懂非懂.不知不觉过去七个月了,对JS的理解更深刻了,数据结构与算法的基础也基本上算是过了一遍了,接下来要把设计模式搞定,然后不再深层次研究JS了,而是学习前端自动化 ...

  2. js设计模式(12)---职责链模式

    0.前言 老实讲,看设计模式真得很痛苦,一则阅读过的代码太少:二则从来或者从没意识到使用过这些东西.所以我采用了看书(<js设计模式>)和阅读博客(大叔.alloyteam.聂微东)相结合 ...

  3. JS设计模式——5.单体模式

    JS设计模式——5.单体模式 http://www.cnblogs.com/JChen666/p/3610585.html   单体模式的优势 用了这么久的单体模式,竟全然不知!用它具体有哪些好处呢? ...

  4. js设计模式总结1

    js设计模式有很多种,知道不代表会用,更不代表理解,为了更好的理解每个设计模式,对每个设计模式进行总结,以后只要看到总结,就能知道该设计模式的作用,以及模式存在的优缺点,使用范围. 本文主要参考张容铭 ...

  5. js设计模式——4.迭代器模式

    js设计模式——4.迭代器模式 代码演示 /*js设计模式——迭代器模式*/ class Iterator { constructor(container) { this.list = contain ...

  6. js设计模式——1.代理模式

    js设计模式——1.代理模式 以下是代码示例 /*js设计模式——代理模式*/ class ReadImg { constructor(fileName) { this.fileName = file ...

  7. 《2016ThoughtWorks技术雷达峰会----js爆炸下的技术选型》

    JS爆炸下的技术选型  刘尚奇    ThoughtWorks, 高级咨询师 JS每6个星期出现一个新框架,那么如何进行JS的选型.以下从四个方面来分析. 1.工具 NPM for all the t ...

  8. Js获取下拉框选定项的值和文本

    Js获取下拉框的值和文本网上提供了2种方法:但有些人很不负责任,他们根本没考虑到浏览器之间的差异导致的错误,导致很多新手琢磨了半天找不出错误! 下面我总结下Firefox和IE下获取下拉框选定项的值和 ...

  9. js 设计模式-接口

    js模拟java接口检测函数:确保子类实现接口中的方法:(出自js设计模式) 上代码: <script type="text/javascript" > <%-- ...

  10. 前端笔记之JavaScript面向对象(三)初识ES6&underscore.js&EChart.js&设计模式&贪吃蛇开发

    一.ES6语法 ES6中对数组新增了几个函数:map().filter().reduce() ES5新增的forEach(). 都是一些语法糖. 1.1 forEach()遍历数组 forEach() ...

随机推荐

  1. centos8 测地卸载php5.6 与卸载php7

    centos8 yum php 默认安装 php7.1.2 我想卸载php7 ,安装php5.6 yum remove php 无法彻底卸载干净.必须强制删除,使用下面命令查看全部php软件包 rpm ...

  2. MySQL 数据分组后取第一条数据

    SQL SERVER数据分组后取第一条数据--PARTITION BY -- 不加 distinct(a.id) order by 会有问题 导致获取出来的数据不对 SELECT id,title,d ...

  3. Python办公自动化_Excel篇

    Python办公自动化_Excel篇 库名 作用 xlrd 从excel中读取数据,支持xls,xlsx xlwt 从excel进行修改操作,不支持对xlsx格式的修改 xlutils 在xlrd和x ...

  4. Java实现压缩文件浅谈

    背景: 在Java中,可以使用java.util.zip包提供的类来进行文件的压缩和解压缩操作.主要涉及的类有ZipOutputStream.ZipEntry.ZipInputStream和Infla ...

  5. ChatGPT插件权限给Plus用户放开了

    大家好,我是章北海mlpy ChatGPT插件权限给Plus用户放开了 我稍微测试了俩,感觉还行,后续我会对一些热门插件深入测测,敬请期待. 官方对插件的介绍如下: 1.插件由非由OpenAI控制的第 ...

  6. JSP | 常见 JSP 简答题

    一.简述 JSP 的工作原理 当我们访问一个JSP页面的时候,这个文件首先会被JSP引擎翻译为一个Java源文件,其实就是一个Servlet,并进行编译,然后像其他Servlet一样,由Servlet ...

  7. @Constraint注解,做特殊的入参校验

    // @Constraint 是 Java 中的注解之一,用于标记自定义的约束注解.约束注解通常用于数据验证,用来限制字段的取值或格式,确保数据的合法性. @Constraint(validatedB ...

  8. mysql备份恢复总结

    mysqldump备份注:例子中的语句都是在mysql5.6下执行------------------基础------------------------一.修改my.cnf文件 vi /etc/my ...

  9. 浅谈 Docker 网络:单节点单容器

    1.Docker 网络模型 Docker 在 1.7 版本中将容器网络部分代码抽离出来作为 Docker 的网络库,叫 libnetwork.libnetwork 中使用 CNM(Container ...

  10. Mathpix:屏幕截图 ➡ latex 公式,一键转换

    安利一天能免费使用 10 次且好用的工具 Mathpix.