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;
}
})();