创建型设计模式包括:单例模式、工厂模式、建造者模式、原型模式
单例模式:
概念:单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命令空间的提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
单例模式实现无法修改的静态变量:
作用:
1)模块间通信
2)系统中某个类的对象只能存在一个
3)保护自己的属性和方法
注意事项:
1)注意this的使用
2)闭包容易造成内存泄露,不需要的就清除掉
3)注意new的成本。(继承)
单例模式的例子:
var xiaowang=(function(argument){
var xiaowangjia=function(message){
this.menling=message;
}
var men;
var info={
sendMessage:function(message){
if(!men){
men=new xiaowangjia(message)
};
return men;
}
}
return info;
})();
var xiaoli={
callXiaowang:function(msg){
var _xw=xiaowang.sendMessage(msg);
console.log(_xw.menling)
}
}
xiaoli.callXiaowang("didi");
静态变量:只能访问不能修改并且无创建后就能使用这一特点。
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
总结:单例模式又被称为单体模式,是只允许实例化一次对象类。用一个对象来规划一个命名空间,井井有条地管理对象上的属性和方法。也可以用来管理代码库中的各个模块。如果想让系统中只存在一个对象,那么单例模式则是最佳的解决方案。
工厂模式
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型(抽象工厂)
这个模式十分有用,尤其是创建对象的流程赋值的时候,比如依赖于很多设置文件等,并且,你会经常在程序中看到工厂方法,用于让子类定义需要创建的对象类型。
模式的作用:
1.对象的构建十分复杂
2.需要依赖具体的环境创建不同的实例
3.处理大量具有相同属性的小对象
注意事项:
1.不能滥用工厂,有时候仅仅是给代码增加复杂度。
简单工厂模式:又叫静态工厂方法,有一个工厂对象决定创建某一种产品对象的实例。主要用来创建同一类对象。
简单工厂的例子:
function createPerson(name,age){
//创建一个对象,并对对象扩展属性和方法
var o=new Object();
o.name=name;
o.age=age;
o.getName=function(){
console.log(this.name);
}
return o;
}
var person1=createPerson("lucky","12");
var person2=createPerson("jack","8");
person1.getName();//lucky
person2.getName();//jack
工厂方法模式:通过对产品类的抽象使其创建业务主要负责用于创建产品的实例。
工厂方法模式的例子:
//安全模式创建的工厂类
var Factory=function(type,content){
if(this instanceof Factory){
var s=new this[type](content);
}else{
return new Factory(type,content);
}
}
//工厂原型中设置创建所有类型数据对象的基类
Factory.prototype={
JavaScript:function(content){
//....
},
jQuery:function(content){
//...
},
vue:function(content){
this.content=content;
(function(content){
var div=document.createElement('div');
div.innerHTML=content;
div.style.border="1px solid pink";
document.getElementById('container').appendChild(div);
})(content);
}
}
抽象工厂模式:通过对类的工厂抽象使其业务用于对产品类簇的创建,不负责创建某一类产品的实例。
抽象工厂模式例子:
//抽象工厂的方法
var VFactory=function(subType,superType){
//判断抽象工厂中是否有该抽象类
if(typeOf VFactory[superType]==='function'){
//缓存类
function F(){};
//继承父类的属性和方法
F.prototype=new VFactory[superType]();
//将子类constructor指向子类
subType.constructor=subType;
//子类原型继承父类
subType.prototype=new F();
}else{
//不存在抽象类抛出错误
throw new Error('未创建该抽象类');
}
}
//小汽车抽象类
VFactory.Car=function(){
this.type='car';
}
VFactory.Car.prototype={
getPrice:function(){
return new Error('抽象方法不能调用');
},
getSpeed:function(){
return new Error('抽象方法不能调用');
}
}
//宝马汽车子类
var BMW=function(price,speed){
this.price=price;
this.speed=speed;
}
//抽象工厂实现对Car抽象类的继承
VFactory(BMW,'Car');
BMW.prototype.getPrice=function(){
return this.price;
}
BMW.prototype.getSpeed=function(){
return this.speed;
}
var A5=new BMW(100000,1000);
console.log(A5.getPrice());//100000
console.log(A5.getSpeed());//1000
三者区别:
简单工厂模式创建的是单一对象,工厂方法模式创建的是多类对象,抽象工厂模式创建出的结果不是一个真实的对象实例,而是一个类簇,它制定了类的结构。简单理解就是只留一个接口,不做具体的事,子类去继承,然后自己做自己的事。
建造者模式
建造者模式可以将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。也就是说我们用了建造者模式,那么用户就需要制定需要建造的类型就可以得到它们,而具体建造的过程和细节就不需要知道了,建造者模式实际,就是一个指挥者,一个建造者,一个使用指挥者调用具体建造者工作得出结果的客户。
作用:
1.分步创建一个复杂的对象
2.解耦封装过程和具体创建的组件
3.无需关心组件如何组装
注意事项:
1.一定要一个稳定的算法进行支持
2.加工工艺是暴露的
建造者模式例子:
//传出的东西是房子
//baogongtou调用工人进行开工,而且他要很清楚工人们的具体的某一个大项
//工人是盖房子的 ,工人可以建卧室、客厅、厨房
//包工头只是一个接口,他不干活,只是对外说我能盖房子
function Fangzi(){
this.woshi="";
this.keting="";
this.chufang="";
}
function Baogongtou(){
this.gaifangzi=function(gongren){
gongren.jian_woshi();
gongren.jian_keting();
gongren.jian_chufang();
}
}
function Gongren(){
this.jian_woshi=function(){
console.log("卧室盖好了");
}
this.jian_keting=function(){
console.log("客厅建好了");
}
this.jian_chufang=function(){
console.log("厨房建好了");
}
//单例模式
this.jiaogong=function(){
var _fangzi=new Fangzi();
_fangzi.woshi="ok";
_fangzi.keting="ok";
_fangzi.chufang="ok";
return _fangzi;
}
}
var gongren=new Gongren();
var baogongtou=new Baogongtou();
baogongtou.gaifangzi(gongren);
var myfangzi=gongren.jiaogong();
console.log(myfangzi);
工厂模式与建造者模式的比较:
工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出(创建)的是什么,不关心你创建的整个过程,仅仅需要知道你最终创建的结果。建造者模式的目的也是为了创建对象,但是它更多关心的是创建这个对象的整个过程,甚至于创建对象的每个细节。
原型模式
用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性和方法。
原型模式的例子:
//原型模式实现继承
function A(firstName){
this.firstName=firstName
}
A.prototype.getFirstName=function(){
console.log(this.firstName);
}
function B(firstName,lastName){
A.call(this,firstName)
this.lastName=lastName;
}
B.prototype=new A();
A.prototype.constructor=B;
B.prototype.getLastName=function(){
console.log(this.lastName);
}
var person=new B("远","方");
person.getFirstName();
person.getLastName();
//原型模式也可以用在对象的创建上。比如创建一个实例对象的构造函数比较复杂,或者耗时比较长,或者通过创建多个对象来实现
function prototypeExtend(){
var F=function(){},
args=arguments,
len=args.length;
for(var i=0;i<len;i++){
for(var j in args[i]){
F.prototype[j]=args[i][j];
}
}
return new F();
}
var cat=prototypeExtend({
food:'fishes',
eat:function(){
console.log(`cat like eating ${this.food} `);
}
})
cat.eat();