创建型设计模式有简单工厂模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式,单例模式。
简单工厂模式
简单工厂模式,又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
工厂角色:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
抽象角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品角色:简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。一般来讲它是抽象产品类的子类,实现了抽象产品类中定义的所有接口方法。
根据简单工厂模式 来封装自定义弹框的代码如下:
function createPop(type,text){
//创建一个对象,并对对象拓展属性和方法
var o=new Object();
o.content=text;
o.show=function(){//显示方法};
if(type=='alert'){
//d
}
}
工厂方法模式
工厂方法模式的对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作推延到其子类去完成。
Factory Method模式的两种情况:一是Creator类是一个抽象类且它不提供它所声明的工厂方法的实现;二是Creator是一个具体的类且它提供一个工厂方法的缺省实现。
工厂方法是可以带参数的。
工厂的作用并不仅仅只是创建一个对象,它还可以做对象的初始化,参数的设置等。
效果:
用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。
Factory Method模式通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。
适用性:
当一个类不知道它所必须创建的对象的类的时候。
当一个类希望由它的子类来指定它所创建的对象的时候。
当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
代码如下:
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){
//.........
}
}
抽象工厂模式:通过对类的工厂抽象使其业务用于对产品类簇的创建,而不负责创建某一类产品的实例。
抽象类在JavaScript中abstract还是一个保留字,所以目前来说还不能像传统面向对象语言那样轻松地创建。抽象类是一种声明但不能使用的类,当你使用时就会报错。所以我们可以在类中手动地抛出错误来模拟抽象类
var Car=function(){};
Car.prototype={
getPrice:function(){
return new Error('抽象方法不能调用');
},
getSpeed:function(){
return new Error('抽象方法不能调用');
}
}
创建的Car类其实什么都不能做,所以我们需要抽象与实现。
//宝马汽车子类
var BMW=function(price,speed){
this.price=price;
this.speed=speed;
}
//抽象工厂方法
var VehicleFactory=function(subType,superType){
if(typeof VehicleFactory[superType]==='function'){
function F(){};
F.prototype=new VehicleFactory[superType]();
subType.constructor=subType;
subType.prototype=new F();
}else{
throw new Error('未创建该抽象类');
}
}
//抽象工厂实现对Car抽象类的继承
VehicleFactory(BMW,'Car');
BMW.prototype.getPrice=function(){
return this.price;
}
BMW.prototype.getSpeed=function(){
return this.speed;
}
//兰博基尼
var lamborghini=function(price,speed){
this.price=price;
this.speed=speed;
}
VehicleFactory(lamborghini,'Car');
lamborghini.prototype.getPrice=function(){
return this.price;
}
lamborghini.prototype.getSpeed=function(){
return this.speed;
}
建造者模式
建造者模式:将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示。
建造者模式是创建这个对象的整个过程,甚至于创建对象的每一个细节,代码如下:
//创建一位人类
var Human=function(param){
//技能
this.skill=param && param.skill || '保密';
//兴趣爱好
this.hobby=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;
default :
that.work=work;
that.workDescript='没有职位描述';
}
})(work,that);
}
//更换期望的职位
Work.prototype.changeWork=function(work){this.work=work;}
//添加对职位的描述
Work.prototype.changeDescript=function(setence){
this.workDescript=setence;
}
建造者模式可得到创建的结果,对于创建的具体实现的细节也参与了干涉,这种模式创建的对象是一个复合对象。
原型模式
原型模式:用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法。
原型对象时一个共享的对象,那么不论是父类的实例对象或者是子类的继承,都是对它的一个指向引用,所以原型对象才会被共享。既然被共享,那么对原型对象的拓展,不论是子类或者父类的实例对象都会继承下来。
创建一个实例对象的构造函数比较复杂,或者耗时比较长,或者通过创建多个对象来实现。此时我们最好不要用new关键字去复制这些基类,但可以通过对这些对象属性或者方法进行复制来实现创建,这是原型模式的最初思想。
function prototypeExtend(){
var F=function(){},args=arguments,i=0,len=args.length;
for(;i < len ; i++){
for(var j in args[i]){
F.prototype[j]=args[i][j];
}
}
return new F();
}
var penguin=prototypeExtend({
speed:20,
swim:function(){
console.log('游泳速度'+this.speed);
},{
run:function(speed){
console.log('奔跑速度'+speed);
},{
jump:function(){
console.log('跳跃动作');
}
});
原型模式可以让多个对象分享同一个原型对象的属性与方法,这也是一种继承方式,不过这种继承的实现是不需要创建的,而是将原型对象分享给那些继承的对象。当然有时需要让每个继承对象独立拥有一份原型对象,此时我们就需要对原型对象进行复制。
由此我们可以看出,原先对象更合适在创建复杂的对象时,对于那些需求一直在变化而导致对象结构不停地改变时,将那些比较稳定的属性与方法共用而提取的继承的实现。
单例模式
单例模式:又被称为单体模式,是只允许实例化一次的对象类。有时我们也用一个对象来规划一个命名空间,井井有条地管理对象上的属性与方法。
1.命名空间的管理员
命名空间使代码更易懂,人们常常用单词或者拼音定义变量或者方法,但由于人们可用的单词或者汉子拼音是有限的,所以不同的人定义的变量使用的单词名称很有可能重复,此时就需要命名空间来约束每个人定义的变量来解决这类问题。
2.模块分明
雅虎的YUI都是通过单例模式来控制自己的每个功能模块的,当添加设置元素class方法,插入一个元素方法时,他们会放到dom模块;当添加事件中阻止事件的冒泡方法,阻止事件的默认行为方法的时候,会放到event模块里;当添加去除字符串首尾空白字符方法,将字符串进行html编码。
3.惰性单例
有时候对于单例对象需要延迟创建,所以在单例中还存在一种延迟创建的形式。
var LazySingle=(function(){
var _instance=null;
function Single(){
return {publicMethod:function(){},publicProperty:'1.0'}
}
return function(){
if(!_instance){
_instance=Single();
}
return _instance;
}
})();
故:
单例模式是一个允许实例化一次的对象类,有时这么做也是为了 节省系统资源,当然JavaScript中单例模式经常作为命名空间对象来实现,通过单例对象我们可以将各个模块的代码井井有条的梳理在一起。
总结:
创建型设计模式是一类处理对象创建的设计模式,通过某种方式控制对象的创建来避免基本对象创建时可能导致设计上的问题或者增加设计上的复杂度。