JS 设计模式 - 工厂模式、单例模式、观察者模式

设计模式让我们按某种方式实现一些功能,增强了代码的可读性。

设计模式需要有面向对象的思想,有Java基础的话理解就更透彻了;看个人喜好,对你有帮助去用,而不是为了用而用。

函数定义

几种函数声明方法:

  • 普通

      function user(){...};
    
  • 挂载到原型链

      var user = function(){...};
      // 声明式,添加方法到原型链上
      user.prototype.addName = function(){...};
      // 重写式,重写原型链
      user.prototype = {
      	addName(){...}
      };
    
  • 修改Function对象,扩展一个添加函数addMethod 这种方式还没用过

      Function.prototype.addMethod = function(name,fn){
      	this.prototype[name] = fn;	
      }
      var user = function(){...};
      user.addMethod("addName",function(){...});
    

设计模式三个特性:

  1. 接口:提供统一方法

  2. 封装:信息私有

     function User(){
     	let tip = "welcome";                  // 内部私有属性
     	this.name = "admin";
     	this.age = 34;
     	this.setAge=function(){};
     	this.getAge=function(){};
     }
     let user = new User();      // user 是访问不到tip 的。 
    
  3. 继承:属性、方法重用

     	// 定义测试父类
     	function Parent(){
     		this.name = "parent";
     	}
     	Parent.prototype.getName = function(){
     		return this.name;
     	}
    

    类式继承

     	function Child(){} 
     	Child.prototype = new Parent();
    

    访问到父类中的公共属性和方法。
    构造函数继承

     	function Child(){
     		Parent.call(this,"child");
     	}
     	// 修改一下父类的构造方法
     	function Parent(name){
     		this.name = name;
     	}
    

    改变子类实例化父类时共有属性的值。

    组合继承

工厂模式

将众多小模块对象封装到一个大对象中实现一个功能。

简单工厂模式

返回差异部分的不同实例或者返回一个新的对象。

用户登陆获取各自的权限:

function User(name){
	let user = new Object();
	user.show = function(){
		console.log("欢迎登陆!");
	}
	if(name == "admin"){
		// 管理员权限
	}
	if(name=="test"){
		// 测试人员权限
	}
	
	return user;
}
工厂方法模式

通过不同类型创建并返回实例。

不同用户行使各自权利:

function User(name){
	if(this instanceof User){
		return new this[name]();
	}else{
		return new User(name);               // 处理不是按照类的实例化方式调用
	}
}
User.prototype = {
	admin:function(){
		this.name = "admin";
		this.show = function(){
			console.log("欢迎管理员登陆!");	
		}
	},
	test:function(){
		this.name = "test";
		this.show = function(){
			console.log("欢迎测试员登陆!");	
		}
	}
}
抽象工厂模式

在工厂中定义父类集,并定义要子类需要实现的方法。父类无法在实例化中调用这些方法。

单例模式

只允许实例化一次的对象类。

命名空间方式定义居多:

	let User = {
		setName:function(name){
			this.name = name;
		},
		getName:function(){
			return this.name;
		}
	}

立即执行函数进行延迟调用创建:

let User = (function(){
	let instance = null;
	function CreateUser(){
		return {
			setName:function(name){
				this.name = name;
			},
			getName:function(){
				return this.name;
			}
		}	
	}
	return function(){
		if(!instance){
				instance = CreateUser();
		}
		return instance;
	}
})();
适配器 模式

解决差异,适配两个组件代码中不同的部分;

比如在处理数据格式时:

// 如果调用者传入对象方式
function User(obj){
	let info = {
		name:obj.name,
		age:obj.age
	}
	// 其他引用属性处理的逻辑 info.name
}
// 如果他改为数组方式传递
function User(arr){
	let info = {
		name:arr[0],
		age:arr[1]
	}
	// 其他引用属性处理的逻辑 info.name
}

改动的只有适配格式的那一块代码,后面的大量逻辑代码中使用的变量不会受到影响。

观察者模式

解决模块间的通信问题,保持数据同步。

	function Observer(){
		let message = {};                // 消息队列
		return {
			regist:function(type,callback){
				// 注册事件 接受两个参数 事件类型、处理函数
				if(message[type]){
					message[type].push(callback);	
				}else{
					message[type] = [callback];
				}
			},
			publish:function(type,args){
				// 发布事件 接受两个参数 事件类型、处理参数
				if(!message[type]){
					return;
				}
				let list = message[type];
				for(let i=0,len = list.length;i<len;i++){
					list[i].call(this,args);
				}
			},
			remove:function(type,callback){
				// 注销方法,
				if(message[type] instanceof Array){
					let list = message[type];
					for(let len = list.length, i=len-1;i>-1;i--){
						list[i] === callback&&list.splice(i,1);
					}
				}
			}
		}
	}

	//
	let User = Observer();
	User.regist("test",function(){console.log("test")});
	User.publish("test","aaa");
委托模式

把多个对象接受统一处理请求都委托给另一个对象处理。

常见的给列表项加点击事件:

let items = document.getElementsByTagName("li");
for(let i=0;i<items.length;i++){
		items[i].onclick = function(e){               // 给每一个li  项都加了点击事件
			console.log(e.target.innerHTML);	
		}
}

// 利用事件冒泡给事件元素的父元素添加点击事件,通过对比事件源分类处理

let parent = document.getElementsByTagName("ul");
parent[0].onclick = function(e){                     // 这样只需要添加一次事件减少内存消耗
	console.log(e.target.innerHTML);	
}

JQuery中的事件监听方法就是委托模式on,可以给动态添加的元素添加点击事件。

之前写过的文章中提到过处理动态DOM元素事件添加

jquery实现级联遇到的ajax同步请求、动态DOM元素监听事件

参考资料:

  • JavaScript 设计模式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heroboyluck

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值