结构型设计模式-提高可复用性(桥接模式、享元模式、模板方法模式)

  • 复用性要点:

  1. 对象可以再重复使用,不用修改
  2. 重复代码少
  3. 模块功能单一

 

桥接模式

目的:通过桥接代替耦合,
应用场景:减少模块之间的耦合,

一:基本结构

// 有三种形状,每种形状都有三种颜色

// 把颜色方法抽离出来 三种形状再调用
function rect(color){
	showcolor(color)
}
function circle(color){
	showcolor(color)
}
function delta(color){
	showcolor(color)
}
// 颜色方法
function showcolor(color){
	
}
// 需要的时候只需要传入颜色
new circle('red');
// 对于三种形状 每种形状有3中颜色的需求,可以不用创建9中不同颜色的不同形状

二:示例

例子:创建不同的选中给效果

需求:有一组菜单,上面每种选项都有不同的效果

// menu1,menu2,menu3
function menuItem(word,color){
	this.word = word;
	this.dom = document.createElement('div');
	this.dom.innerHTML = this.word;
	this.color = color;
}
// 绑定方法
menuItem.prototype.bind = function(){
	var self = this;
	this.dow.onmouseover = function(){
		this.style.color = self.color.cOver;
	}
	this.dom.onmouseout = function(){
		this.style.color = self.color.cOut;
	}
}
// 新建颜色对象
function menuColor(cOver,cOut){
	this.cOver = cOver;
	this.cOut = cOut;
}
// 储存菜单数据数组
var data = [
	{
		word:'menu1',
		color:['red','yellow']
	},{
		word:'menu2',
		color:['red','yellow']
	}
]
for (var i = 0;i<data.length;i++) {
	new menuItem(data[i].word,new.menuColor(data[i][0],data[i][1])).bind();
}

例子:Expree中创建get等方法

需求:express中有get,post等七八个方法,如何方便快速创建

首先在express中,可以通过
app.get 设置get请求中间件
app.post 设置post请求中间件
app.delete 设置delete请求中间件


首先创建一个类
function express(){
	
}
// 在express中有methods这么一个数组,通过第三方库require进来的,这里我们直接定义
var methods = ['get','post','delete','put'];
methods.forEach(function(method){
	app[method] = function(){
		// 然后他会借助一个route桥接过来,调用route内的method
		route[method].apply(route,slice.call(arguments,1))
	}
})

 

享元模式

目的:减少对象/代码数量,
应用场景:当代码中创建了大量的类似对象和类似代码块

一:基本结构

// 有一百种不同文字的弹框,每种弹框行为相同,但是文字样式不同,我们没必要新建一百个弹窗对象
function Pop(){
	
}
// 保留同样的行为
Pop.prototype.action = function(){
	
}
Pop.prototype.show = function(){
	// 显示弹框
}
// 提取出每个弹窗会不同的部分作为一个外部的数组
var popArr = [
	{text:'this is win1',style:[400,400]},
	{text:'this is win2',style:[400,100]},
]
var poper = new Pop();
for (var i=0;i<100;i++) {
	poper.show(popArr[i])
}
ps:只需要一个类,不需要new100次;这个类只保留所有弹框共有的,每个弹窗不同的部分留作为一个公共享元,

二:应用示例

例子:文件上传

需求:项目中有一个文件上传的功能,该功能可以上传多个文件

// 数组储存需要上传的
var data = [
	{
		type:'img',
		file:'file1'
	},{
		type:'word',
		file:'file2'
	}
]

function uploader(){
	
}
uploader.prototype.init = function(){
	// 初始化文件上传的html
}
uploader.prototype.delete = function(){
	// 删除掉该html
}
uploader.prototype.uploading = function(fileType,file){
	// 上传
}
var uploader = new uploader();
for(var i=0;i<data.length;i++){
	uploader.uploading(data[i].type,data[i].file)
}

例子:jQuery的extend

需求:extends方法 需要判断参数的数量来进行不同的操作

// 首先extend方法简单讲解一下
$.extend({a:1});//如果给如一个对象,就会扩展到jQuery上面的
$.extend({a:1},{b:1});//如果给两,就会合并再返回 {a:1,b:1}

function extend(){
	// 公共享元 默认第一个arg
	var target = arguments[0];
	// 被拷贝者存为变量
	var source;
	
	if(arguments==1){
		target = this;
		source = arguments[0];
	}else{
		target = arguments[0];
		source = arguments[1];
	}
	
	for(var item in source){
		target[item] = source[item]
	}
	
	// 原来的代码 上面为改造后
	// if(arguments==1){
	// 	for(var item in arguments[0]){
	// 		如果只有一个对象,把他放进this中
	// 		this[item] = arguments[0][item]
	// 	}
	// }else{
	// 	for(var item in arguments[1]){
	// 		如果有多个,则把第二个放进第一个arg中
	// 		arguments[0][item] = arguments[1][item]
	// 	}
	// }
}

模板方法模式

目的:定义一系列操作的骨架,简化后面类似操作的内容,
应用场景:当项目中出现很多类似操作内容

一:基本结构

// 编写一个导航组件 有的带消息提示 有的是竖着 有的是横着
function baseNav(){
	// 基础类 此处定下基本骨架
}
baseNav.prototype.action = function(fn){
	// 特异性处理,留出一个回调等待具体实现
}
ps:导航组件多种多样 之后可能还有增加新类型 那么不妨写一个基础的组件类 然后具体的实现等到具体的使用时在操作

二:应用示例

例子:编写一个弹框组件(继承)

需求:项目有一系列弹窗,每个弹窗的行为大小文字都不一样

// 先定义一个基础弹窗
function basePop(word,size){
	this.word = word;
	this.size = size;
	this.dom = null;
}
// 显示初始化
basePop.prototype.init = function(){
	var div = document.createElement('div');
	div.innerHTML = this.word;
	div.style.width = this.size.width + 'px';
	div.style.height = this.size.height + 'px';
	this.dom = div;
}
// 基础操作
basePop.prototype.hidden = function(){
	this.dom.style.display = 'none';
}
basePop.prototype.confirm = function(){
	this.dom.style.display = 'none';
}

// 定义一个特殊类(ajax弹窗),会继承我们的基础类
function ajaxPop(word,siez){
	basePop.call(this,word,size);
}
// 先继承基础行为
ajaxPop.prototype = new basePop();

// 拿去之前的隐藏行为
var hidden = ajaxPop.prototype.hidden;
// 定义新的隐藏行为
ajaxPop.prototype.hidden = function(){
	// 先调用原有的隐藏行为
	hidden.call(this);
	// 假如特异性行为
	console.log(1);
}

// 确认行为同理
var confirm = ajaxPop.prototype.confirm;
ajaxPop.prototype.confirm = function(){
	confirm.call(this);
	console.log(2);
}

例子:封装一个算法计算器(组合)

需求:现在我们有一系列自己的算法,但是这个算法在不同的地方需要增加一些不同的操作

function counter(){
	// 因为扩展,增加两个队列
	this.beforeCounter = [];
	this.afterCounter = [];
}

// 扩展方法(计算前的,计算后的)
counter.prototype.addBefore = function(fn){
	// 调用就push进队列
	this.beforeCounter.push(fn);
}
counter.prototype.addAfter = function(fn){
	// 调用就push进队列
	this.afterCounter.push(fn);
}

// 基础计算骨架
counter.prototype.count = function(){
	var _resultnum = num;
	var _arr = [baseCount];
	
	// 把_arr拼接成一个队列
	_arr = this.beforeCounter.concat(_arr);
	_arr = _arr.concat(this.afterCounter);
	
	function baseCount(num){
		// num是我们要计算的数据
		num+=4;
		num*=4;
		return num;
	}
	// 当数组大于0就说明还有需要执行的,把第一项拿出来执行传入_resultnum再返回_resultnum;
	while(_arr.length>0){
		_resultnum = _arr.shift()(_resultnum);
	}
	return _resultnum;
}

// 接下来就是使用了
var counterObj = new counter();
counterObj.addBefore(function(num){
	num--;
	return num;
})
counterObj.addAfter(function(num){
	num*=2;
	return num;
})
counterObj.count(10);

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值