常见工厂模式总结

1,简单工厂模式

    简单工厂模式又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象。

1.1 一个未使用工厂模式的例子
//篮球类
var Basketball = function(){
	this.intro = '这是个篮球';
}
Basketball.prototype = {
	getMember:function(){},
	getBallSize:function(){},
}
//足球类
var Football = function(){
	this.intro = '这是一个足球';
}
Football.prototype = {
	getMember:function(){};
	getBallSize:function(){};
}
//网球类
var Tennis = function(){
	this.intro = '这是一个网球';
}
Tennis.prototype = {
	getMember:function(){};
	getBallSize:function(){};
}

    如上所述,该模块对外有3个类接口. 

1.2 使用一个类接口

    上面的3个类可以使用下面的一个类进行管理,下面的这个就是一个工厂模式,这样对外的接口就只有一个.

//运动工厂
var SportsFactory = function(name){
	switch(name){
		case 'NBA':
			return new Basketball();
		case 'wordCup':
			return new Football();
		case 'FrenchOpen':
			return new Tennis();
	}
}
1.3 使用一个对象管理

    复用共同特性,区别差异特性

function createPop(type,text){
	//创建一个对象,并对对象扩展属性和方法
	var o = new Object();
	o.content = text;
	o.show = function(){
		//显示方法
	};
	if(type == 'alert'){
		...
	}
	if(type == 'prompt'){
		...
	}
	if(type == 'confirm'){
		...
	}
	//将对象返回
	return o;
}
//创建警示框
var userNameAlert = createPop('alert','用户名只能是26个字母和数字');

2,工厂方法模式

    工厂方法模式本意是将实际创建对象工资推迟到子类当中。这样核心类就成了抽象类。

2.1 简单工厂模式实例

    先看一个简单工厂模式实例如下,使用一个学科类工厂管理多个类. 

//创建JAVA学科类
var java = function(content){
	//将内容保存在content里面以备日后使用
	this.content = content;
	//创建对象时,通过闭包,直接执行,将内容按需求的样式插入到页面内
	(function(content){
		var div = document.createElement('div');
		div.innerHTML = content;
		div.style.color = 'green';
		document.getElementById('container').appendChild(div);
	})(content);
}
//创建PHP学科类
var Php = function(content){
	this.content = content;
	(function(content){
		var div = document.createElement('div');
		div.innerHTML = content;
		div.style.color = 'yellow';
		div.style.bacground = 'red';
		document.getElementById('container').appendChild(div);
	})(content);
}
//创建JavaScript学科类
var JavaScript = function(content){
	this.content = content;
	(function(content){
		var div = document.createElement('div');
		div.innerHTML = content;
		div.style.background = 'pink';
		document.getElementById('container').appendChild(div);
	})(content);
}
//学科类工厂
function JobFactory(type,content){
	switch(type){
		case 'java':
			return new Java(content);
		case 'php':
			return new Php(content);
		case 'JavaScript':
			return new JavaScript(content);
	}
}
2.2 使用安全模式和prototype

    使用安全模式和prototype创建一个每向工厂中添加一个方法只要修改一处的工厂模式,在2.1 中,每添加一个类,都要修改两出,一处新增这个需求的类,一处是向工厂中添加一个类指向。这样是很不方便的... 

//安全模式创建的工厂类
var Factory = function(type,content){
	if(this instanceof Factory){
		var s = new this[type](content);
		return s;
	}else{
		return new Factory(type,content);
	}
}
//工厂原型中社会中创建所有类型数据对象的基类
Factory.prototype = {
	Java:function(content){
		//...
	},
	JavaScript:function(content){
		//...
	},
	php:function(content){
		//...
	}
};
3,抽象工厂模式

    抽象工厂模式通过对类的工厂抽象使其业务用于产品类镞的创建,而不复杂创建某一类产品的实例。

3.1 JavaScript中的抽象类

    JavaScript中严格上来说是没有抽象类的,因为JavaScript中并没有实现abstract关键字,但是可以人为的实现一个抽象类如下:

//汽车抽象类,当使用其实例对象的方法是会抛出错误
var Car = function(){};
Car.prototype = {
	getPrice:function(){
		return new Error('抽象方法不能调用');
	},
	getSpeed:function(){
		return new Error('抽象方法不能调用');
	}
};

    如上面定义的抽象类,当使用其实例对象时会报错,但是可以通过在实现其子类时覆盖此类方法。如果在子类中没有覆盖这些方法,在调用时就会报错. 

3.2 抽象工厂模式
//抽象工厂方法
var VehicleFactory = function(subType,superType){
	//判断抽象工厂中是否有该抽象类
	if(typeof VehicleFactory[superType] === 'function'){
		//缓存类
		function F(){};
		//继承父类属性和方法
		F.prototype = new VehicleFactory[superType]();
		//将子类constructor指向子类
		subType.constructor = subType;
		//子类原型继承"父类"
		subType.prototype = new F();
	}else{
		//不存在该抽象类抛出错误
		throw new Error('未创建该抽象类');
	}
}
//小汽车抽象类
VehicleFactory.Car = function(){
	this.type = 'Car';
};
VehicleFactory.Car.prototype = {
	getPrice:function(){
		return new Error('抽象方法不能调用');
	},
	getSpeed:function(){
		return new Error('抽象方法不能调用');
	}
}
//公交车抽象类
VehicleFactory.Bus = function(){
	this.type = 'Bus';
};
VehicleFactory.Bus.prototype = {
	getPrice:function(){
		return new Error('抽象方法不能调用');
	},
	getPassengerNum:function(){
		return new Error('抽象方法不能调用');
	}
}

    抽象工厂实际上是一个实现子类继承父类的方法,在这个方法中我们需要通过传递子类以及要继承父类(抽象类)的名称,并且在抽象工厂方法中又增加了一次对抽象类存在性的一次判断,如果存在,则将子类继承父类的方法。然后子类通过寄生式继承。继承父类过程中有一个地方需要注意,就是在对过渡类的原型继承时,我们不说继承父类的原型,而是通过new关键字复制的父类的一个实例,这么做是因为过渡类不应仅仅继承父类的原型方法,还要继承父类的对象属性,所以通过new关键字将父类的构造函数执行一遍来复制构造函数中的属性和方法。

3.3,抽象与实现
//宝马汽车子类
var BMW = function(price,speed){
	this.price = price;
	this.speed = speed;
}
//抽象工厂实现对Car抽象类的继承
VehicleFactory(BMW,'Car');
BMW.prototype.getPrice = function(){
	return this.price;
}
BMW.prototype.getSpeed = function(){
	return this.speed'
}

    抽象工厂模式是设计模式中最抽象的一种,也是创建模式中唯一一种抽象画创建模式。该模式创建出的结果不是一个真实的对象实例,而是一个类镞,它制定了类的结构,这也就区别了简单工厂模式创建单一对象,工厂方法模式创建多类对象。

4,建造者模式

    建造者模式:用于将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示。

    建造者模式和工厂模式的区别,工厂模式只关系最后创建的对象是怎样的,而建造者模式在创建对象时候还关注创建的细节,如下是一个建造者模式的例子:

//创建一位人类
var Human = function(param){
	//技能
	this.skill = param && param.skill || '保密';
	//兴趣爱好
	this.body = param && param.hobby || '保密';
}
//人类原型方法
Human.prototype = {
	getSkill:function(){
		return this.skill;
	},
	getHobby:function(){
		return this.hobby;
	}
}
//实例化姓名类
var Named = function(name){
	var that = this;
	//构造器
	//构造函数解析姓名的姓与名
	(function(name,that){
		that.wholeName = name;
		if(name.indexOf(' ')>-1){
			that.FirstName = name.slice(0,name.indexOf(' '));
			that.secondName = name.slice(name.indexOf(' '));
		}
	})(name,that);
}
//实例化职位类
var Work = function(work){
	var that = this;
	//构造器
	//构造函数中通过传入的职位特征来设置相应职位以及描述
	(function(work,that){
		switch(work){
			case 'code':
				that.work = '工程师';
				that.workDescript = '每天沉醉于编程';
				break;
			case 'UI':
			case 'UE':
				that.work = '设计师';
				that.workDescript = '设计更似一种艺术';
				break;
			case 'teach':
				that.work = '教师';
				that.workDescript = '分享也是一种快乐';
				break;
			default:
				that.work = work;
				that.workDescript = '对不起,我们还不清楚你所选择职位的相关描述';
		}
	})(work,that);
}
//更换期望的职位
Work.prototype.changeWork = function(work){
	this.work = work;
}
//添加对职位的描述
Work.prototype.changeDescript = function(setence){
	this.workDescript = setence;
}

/****
 *应聘者建造者
 *参数name:姓名(全名)
 *参数work:期望职位
 **/
 var Person = function(name,work){
	 //创建应聘者缓存对象
	 var _person = new Human();
	 //创建应聘者姓名解析对象
	 _person.name = new Named(name);
	 //创建应聘者期望职位
	 _person.work = new Work(work);
	 //将创建的应聘者对象返回
	 return _person;
 }
 

5,原型模式

    原型模式:用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法。

5.1 语言中的原型

    使用prototype创建同一类对象的属性和方法共享

5.2 创建一个焦点图

    先看一个没有使用原型模式的代码片段如下:

//图片轮播类
var LoopImages = function(imgArr,container){
	this.imagesArray = imgArr;   //轮播图片数组
	this.container = container;		//轮播图片容器
	this.createImage = function(){}		//创建轮播图片
	this.changeImage = function(){}		//切换下一张图片
}

//上下滑动切换类
var SlideLoopImg = function(imgArr,container){
	//构造函数继承图片轮播类
	LoopImages.call(this,imgArr,container);
	//重写继承的切换下一张图片方法
	this.changeImage = function(){
		console.log('SlideLoopImg changeImage function');
	}
}

//渐隐切换类
var FadeLoopImg = function(imgArr,container,arrow){
	LoopImages.call(this,imgArr,container);
	//切换箭头私有变量
	this.arrow = arrow;
	this.changeImage = function(){
		console.log('FadeLoopImg changeImage function');
	}
}

    在这种方式中,每次新建一个对象时,新建一个滑动切换类时,对在父类空间中,父类的4个属性都会被复制一次,但是实际上父类的属性在继承是只要复制前两个就可以了。再看如下的代码片段:

//图片轮播类
var LoopImages = function(imgArr,container){
	this.imagesArray = imgArr;  	//轮播图片数组
	this.container = container;		//轮播图片容器
}
LoopImages.prototype = {
	//创建轮播图片
	createImgae:function(){
		console.log('LoopImages createImage function');
	},
	//切换下一张图片
	changeImage:function(){
		console.log('LoopImages changeImage funciton');
	}
}
//上下滑动切换类
var SlideLoopImg = function(imgArr,container){
	//构造函数继承图片轮播类
	LoopImages.call(this,imgArr,container);
}
SlideLoopImg.prototype = new LoopImages();
//重写继承的切换下一张图片方法
SlideLoopImg.prototype.changeImage = function(){
	consle.log('SlideLoopImg changeImage function');
}
//渐隐切换类
var FadeLoopImg = function(imgArr,container,arrow){
	LoopImages.call(this,imgArr,container);
	//切换箭头私有变量
	this.arrow = arrow;
}
FadeLoopImg.prototype = new LoopImages();
FadeLoopImg.prototype.changeImage = function(){
	console.lof('FadeLoopImg changeImage function');
}

    在该代码中,子类继承父类的时候,只复制了父类的两个属性. 

6,单例模式

    单例模式又称为单体模式,是只允许实例化一次的对象类。有时我们也用一个对象来规划命名空间,井井有条地管理对象上的属性与方法。

6.1 一个简单的单例模式使用
var A = {
	Util:{
		util_method1:function(){},
		util_method2:function(){}
		...
	}
	Tool:{
		tool_method1:function(){},
		tool_method2:function(){}
		...
	}
}
6.2 使用单例模式实现静态变量
var Conf = (function(){
	//私有变量
	var conf = {
		MAX_NUM:100,
		MIN_NUM:1,
		COUNT:1000
	}
	//返回取值器对象
	return{
		//取值器方法
		get:function(name){
			return conf[name]?conf[name]:null;
		}
	})();
var count = Conf.get('COUNT')
console.log(count)  //1000
6.3 一个惰性单例的例子
//惰性载入单例
var LazySingle = (function(){
	//单例实例引用
	var _instance = null;
	//单例
	function Single(){
		/*这里定义私有属性和方法*/
		return{
			publicMethod:function(){},
			piblicProperty:'1.0'
		}
	}
	//获取单例对象接口
	return function(){
		//如果为创建单例将创建单例
		if(!_instance){
			_instance = Single();
		}
		//返回单例
		return _instance;
	}
})();


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值