js设计模式(下)
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设计模式(下)的更多相关文章
- JS设计模式(一)
刚入职时,看过一段时间的设计模式,似懂非懂.不知不觉过去七个月了,对JS的理解更深刻了,数据结构与算法的基础也基本上算是过了一遍了,接下来要把设计模式搞定,然后不再深层次研究JS了,而是学习前端自动化 ...
- js设计模式(12)---职责链模式
0.前言 老实讲,看设计模式真得很痛苦,一则阅读过的代码太少:二则从来或者从没意识到使用过这些东西.所以我采用了看书(<js设计模式>)和阅读博客(大叔.alloyteam.聂微东)相结合 ...
- JS设计模式——5.单体模式
JS设计模式——5.单体模式 http://www.cnblogs.com/JChen666/p/3610585.html 单体模式的优势 用了这么久的单体模式,竟全然不知!用它具体有哪些好处呢? ...
- js设计模式总结1
js设计模式有很多种,知道不代表会用,更不代表理解,为了更好的理解每个设计模式,对每个设计模式进行总结,以后只要看到总结,就能知道该设计模式的作用,以及模式存在的优缺点,使用范围. 本文主要参考张容铭 ...
- js设计模式——4.迭代器模式
js设计模式——4.迭代器模式 代码演示 /*js设计模式——迭代器模式*/ class Iterator { constructor(container) { this.list = contain ...
- js设计模式——1.代理模式
js设计模式——1.代理模式 以下是代码示例 /*js设计模式——代理模式*/ class ReadImg { constructor(fileName) { this.fileName = file ...
- 《2016ThoughtWorks技术雷达峰会----js爆炸下的技术选型》
JS爆炸下的技术选型 刘尚奇 ThoughtWorks, 高级咨询师 JS每6个星期出现一个新框架,那么如何进行JS的选型.以下从四个方面来分析. 1.工具 NPM for all the t ...
- Js获取下拉框选定项的值和文本
Js获取下拉框的值和文本网上提供了2种方法:但有些人很不负责任,他们根本没考虑到浏览器之间的差异导致的错误,导致很多新手琢磨了半天找不出错误! 下面我总结下Firefox和IE下获取下拉框选定项的值和 ...
- js 设计模式-接口
js模拟java接口检测函数:确保子类实现接口中的方法:(出自js设计模式) 上代码: <script type="text/javascript" > <%-- ...
- 前端笔记之JavaScript面向对象(三)初识ES6&underscore.js&EChart.js&设计模式&贪吃蛇开发
一.ES6语法 ES6中对数组新增了几个函数:map().filter().reduce() ES5新增的forEach(). 都是一些语法糖. 1.1 forEach()遍历数组 forEach() ...
随机推荐
- 用 Java?试试国产轻量的 Solon v1.10.1
相对于 Spring Boot 和 Spring Cloud 的项目: 启动快 5 - 10 倍. (更快) qps 高 2- 3 倍. (更高) 运行时内存节省 1/3 ~ 1/2. (更少) 打包 ...
- Mybatis 模块拆份带来的 Mapper 扫描问题
项目中,两个模块中都放了 Mapper,如下所示 @MapperScan(basePackages ={"com.vipsoft.his.mapper","com.vip ...
- 叫板GPT-4的Gemini,我做了一个聊天网页,可图片输入,附教程
先看效果: 简介 Gemini 是谷歌研发的最新一代大语言模型,目前有三个版本,被称为中杯.大杯.超大杯,Gemini Ultra 号称可与GPT-4一较高低: Gemini Nano(预览访问) 为 ...
- 用 Python 开发的 PDF 抽取Excel表格 2.0版
前些天向大家介绍了我开发的从PDF抽取表格小工具的使用方法(️点击直达),有同学反馈说有一些问题: 一页PDF有多张表,只能抽取第一个 有些表格线条是透明的,无法抽取 一页一页处理太麻烦,不能一次性抽 ...
- 【HZERO】消息发送
消息发送 https://open.hand-china.com/community/detail/625843016338378752 新建模板 @Override public String sh ...
- OJ中的语言选项里G++ 与 C++的区别
概念上: C++是一门计算机编程语言,而G++则是C++的编译器. GCC和G++都是GUN的编译器,cc是Unix系统的C Compiler,而gcc则是GNU Compiler Collectio ...
- ACM:快读读入技巧
快速读入:当数据输入较大时,比scanf快 inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9') ...
- 双非本科拿下oppo sp!这位粉丝太强了!
哈喽,大家好,我是仲一.今天分享的是一位双非本科生拿下oppo sp的秋招经验.当时,这位粉丝咨询我offer选择的时候,看到年薪31W这个数字,我以为他是研究生.后来,再三确认了,他确实是本科生. ...
- 黑马vue学习笔记
1.v-model原理 2.数组相关API 3.prop命名规则: 4.非父子组件传值-事件中心
- java占位符%d,%s等的使用
(转载自:http://www.cnblogs.com/happyday56/p/3996498.html) String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语 ...