建立型设计模式
一、简单工厂模式:
又叫静态工厂方法,由一个工厂对象决定建立某一种产品对象类的实例,主要用来建立同一类对象。
不少刚刚了解面向对象以后会有不少盲区,例如一个关于登陆表单验证的例子:javascript
处理前:java
// 用户名校验 var LoginAlert = function (text) { this.content = text; }; LoginAlert.prototype.show = function () { // 显示警示框 }; var userNameAlert = new LoginAlert('用户名不能多于16个字母或数字'); userNameAlert.show(); // 密码校验 var passwordAlert = new LoginAlert('输入密码不正确'); passwordAlert.show(); // 添加注册按钮 var loginConfirm = function (text) { this.content = text; }; loginConfirm.prototype.show = function () { // 显示确认框 }; var loginFailConfirm = new loginConfirm('您的用户名不存在,请从新输入!'); loginFailConfirm.show(); // 友好自定义提示框 var LoginPrompt = function (text) { this.content = text; }; LoginPrompt.prototype.show = function () { // 显示提示框 };
处理后:编程
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', '用户名不能多于16个字母或数字');
团队项目开发不一样于我的开发,其对全局变量的限制很大,因此咱们要尽可能少建立全局变量。对于同一类对象在不一样需求中的重复性使用,不少
时候不须要重复建立,代码复用是面向对象编程的一条准则。经过对简单工厂来建立一些对象,可让这些对象公用一些资源而又私有一些资源
,这是一种很不错的实践。不过对于简单工厂模式,它的使用场合一般也就限制在建立单一对象。设计模式
二、工厂方法模式:
经过对产品类的抽象使其建立业务主要负责用于建立多类产品的实例数组
处理前:缓存
// 建立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) { // 将内容保存在content里面 以备后日使用 this.content = content; // 建立对象时,经过闭包直接执行,将内容按需求的样式插入到页面内 (function (content) { var div = document.createElement('div'); div.innerHTML = content; div.style.color = 'yellow'; div.style.background = 'red'; document.getElementById('container').appendChild(div); })(content); }; // 建立Javascript学科类 var JavaScript = function (content) { // 将内容保存在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); }; }
处理后:安全
// 安全模式建立工厂类 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) { //..... }, Php: function (content) { //..... }, JavaScript: function (content) { //..... }, UI: function (content) { // 将内容保存在content里面 以备后日使用 this.content = content; // 建立对象时,经过闭包直接执行,将内容按需求的样式插入到页面内 (function (content) { var div = document.createElement('div'); div.innerHTML = content; div.style.background = 'pink'; div.style.border = '1px soild red'; document.getElementById('container').appendChild(div); })(content); }, };
对于建立多类对象,前面学过的简单工厂模式就不太适合了,这是简单工厂模式的应用局限,固然这正是工厂方法模式的价值所在,经过工厂方法模式
咱们能够轻松建立多个类的实例对象,这样工厂方法对象在建立对象的方式也避免了使用者与对象之间的耦合,用户没必要关心建立该对象的具体类,只
须要调用工厂方法便可。闭包
三、抽象工厂模式:
经过对类的工厂抽象使其业务用于对产品类的建立,而不负责建立某一类产品的实例。app
举例:ide
// 汽车抽象类,当使用其实例对象的方法时会抛出错误 var Car = function () {}; Car.prototype = { getPrice: function () { return new Error('抽象方法不能调用'); }, getSpeed: function () { return new Error('抽象方法不能调用'); } };
咱们看到咱们建立的这个car类其实什么都作不了,建立时没有任何属性,然而原型prototype上的方法也不能使用,不然会报错。但在继承上倒是很是
有用,由于定义了一种类而且定义了该类所必备的方法,若是在子类中没有重写这些方法,那么当调用的时候就会报错,这一特色是很必要的,由于在一
些大型应用中,总会有一些子类去继承另外一些父类,这些父类常常会定义一些必要的方法,却没有具体的实现,如car类中的 getPrice()和getSpeed()
方法,那么一旦子类建立了一对象,该对象老是应该具有一些方法的,若是这些方法从父类继承过来就没有具体的实现,那么实例化对象便会调用父类中
的这些方法,若是父类能有一个好的提示,那么对于忘记重写子类的这些错误遗漏的避免是颇有帮助的,这也是抽象类的一个做用,即定义一个产品蔟,
并声明一些方法,若是子类中没有重写就会抛出错误。
// 抽象方法 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('抽象方法不能调用'); } }; // 宝马汽车子类 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; }; // 掉用 var bmw = new BMW(100000, 1000); console.log(bmw.getPrice); // 100000 console.log(bmw.getSpeed); // 1000
抽象工厂模式是设计模式中最抽象的一种,也是建立模式中惟一一种抽象化建立模式,该模式建立出的结果不是一个真实的对象实例,而是一个类簇,它制
定了类的结构,这也是区别于简单工厂模式建立单一对象,工厂方法模式建立多类对象。固然因为JavaScript中不支持抽象化建立与虚拟方法,因此致使
这种模式不能像其余面向对象语言中应用的那么普遍。
四、建立者模式:
将一个复杂对象的构建层与其表示层相互分离,一样的构建过程可采用不一样的表示
// 建立一位人类 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.seconName = name.sile(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; }; var Person = function (name, work) { // 建立应聘者对象 var _preson = new Human(); // 建立应聘者姓名解析对象 _preson.name = new Named(name); // 建立应聘者指望职位 _person.work = new Work(work); // 将建立的应聘者对象返回 return _preson; }; 使用: var person = new Person('xiao ming', 'code'); console.log(person.skill); // 保密 console.log(person.name.FirstName); // xiao console.log(person.work.work); // 工程师 console.log(person.work.workDescript); // 天天在编程中度过 person.work.changeDescript('更改一下职位描述!'); console.log(person.work.workDescript); // 更改一下职位描述
五、原型模式:
用原型实例指向建立对象的类,使用与建立新的对象的类共享原型对象的属性和方法。
处理前:
// 图片轮播类 var LoopImages = function (imgArr, container) { this.imagesArray = imgArr; this.container = container; this.createImage = function () {}; this.changeImage = function () {}; }; // 渐隐切换类 var FadeLoopImage = function (imgArr, container, arrow) { LoopImages.call(this, imgArr, container); // 切换箭头私有变量 this.arrow = arrow; this.changeImage = function () { console.log('FadeLoopImage changeImage function'); }; }; // 实例化一个渐隐切换图片类 var fadeImg = new FadeLoopImage(['01.jpg', '02.jpg', '03.jpg', '04.jpg'], 'slide', ['left.jpg', 'right.jpg']);
处理后:
// 图片轮播类 var LoopImage = function (imgArr, container) { this.imagesArray = imgArr; // 轮播图片数组 this.container = container; // 轮播图片容器 }; // 渐隐切换类 var FadeLoopImage = function (imgArr, container, arrow) { LoopImages.call(this, imgArr, container); // 切换箭头私有变量 this.arrow = arrow; }; FadeLoopImage.prototype = new LoopImages(); FadeLoopImage.prototype.changeImage = function () { console.log('FadeLoopImage changeImage function'); }; // 测试用例 console.log(fadeImg.container); // slide fadeImg.changeImage(); // FadeLoopImage changeImage function // 原型继承 function prototypeExtend () { var F = function () {}; // 缓存类,为实例化返回对象临时建立 args = arguments, i = 0, len = args.length; for (; i< lenl 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.spee) } },{ run: function () { console.log('奔跑速度' + speed) } },{ jump: function () { console.log('跳跃动做') } }); penguin.swim(); // 游泳速度20 penguin.run(10); // 奔跑速度10 penguin.jumo(); // 跳跃动做
六、单例模式:
又称为单体模式,是只容许实例化一次的对象类,有时咱们也用一个对象来规划一个命名空间,层次分明的管理对象上的属性和方法。
案例:
// 惰性载入单例 var LazySingle = (function () { // 单例实例引用 var _instance = null; // 单例 function Single () { // 这里定义了私有的属性和方法 return { publicMethod: function () {}, publicProperty: '1.0' }; }; //获取单例对象接口 return function () { // 若是为建立单例建立单例 if (!_instance) { _instance = Single(); }; // 返回单例 return _instance; }; })(); 测试用例: console.log(LazySingle().publicProperty); // 1.0
单例模式有时也被称为单体模式,它只是一个只容许实例化一次的对象类,有时这么作也是为了节省系统资源。固然Javascript中单例模式常常 做为命名空间对象实现,经过单例对象咱们能够将各个模块的代码层次分明的梳理在一块儿。