// 第一大类、创建型设计模式==一类处理对象创建的设计模式
{
// a、简单工厂模式(又称:静态工厂方法)
function creatObj(name, time, type) {
var o = {};
o.name = name;
o.time = time;
o.type = type;
o.getName = function () {
console.log(this, name);
}
//返回新对象
return o;
}
// b、安全的工厂方法(增加判断instanceof)
var factory = function (type, content) {
if (this instanceof Factory) {
var o = new this[type](content);
return o;
}
};
//工厂原型中设置创建所有类型数据对象的基类
var Factory = function () { };
Factory.prototype = {
java: function (content) { },
php: function (content) { },
ui: function (content) { }
}
// c、抽象工厂模式 (通过对类的工厂抽象使其业务对产品类簇的创建,而不只是一类产品的实例)(抽象类)
var Car = function () { };
Car.prototype = {
getPrice: function () {
console.log("抽象方法不能调用!");
},
getSpeed: function () {
console.log("抽象方法不能调用!");
}
}
var s = new Car();
s.getPrice();
//抽象工厂模式
var VehicleFactory = function (subType, superType) {
//判断抽线工厂中是否有该抽象类
if (typeof VehicleFactory[subType] === 'function') {
//缓存类
function F() { }
//集成父类属性和方法
F.prototype = new VehicleFactory[subType];
//将子类constructor指向子类
subType.constructor = subType;
//子类的原型集成“父类”
subType.prototype = new F();
} else {
//不存在该抽象类
throw new Error("未创建该抽象类");
}
}
//小汽车抽象类
VehicleFactory.Car = function () {
this.type = "car";
}
VehicleFactory.Car.prototype = {
getPrice: function () {
console.log("小汽车方法!");
},
getSpeed: function () {
console.log("小汽车方法!");
}
}
//公交车抽象类
VehicleFactory.Bus = function () {
this.type = "bus";
}
VehicleFactory.Bus.prototype = {
getPrice: function () {
console.log("公交车方法!");
},
getSpeed: function () {
console.log("公交车方法!");
}
}
//货车抽象类
VehicleFactory.Truck = function () {
this.type = "truck";
}
VehicleFactory.Truck.prototype = {
getPrice: function () {
console.log("货车方法!");
},
getSpeed: function () {
console.log("货车方法!");
}
}
//宝马汽车类
var BWM = function (price, speed) {
this.price = peice;
this.speed = speed;
};
// 抽象工厂对Car抽象类实现继承
VehicleFactory(BWM, "Car");//判断是否含有此类
//子类重写父类方法
BWM.prototype.getPrice = function () {
return this.price;
}
//大众汽车类
var DZ = function (price, speed) {
this.price = peice;
this.speed = speed;
};
// 抽象工厂对Car抽象类实现继承
VehicleFactory(DZ, "Car");//判断是否含有此类
DZ.prototype.getPrice = function () {
return this.price;
}
// PS:通过抽象工厂可以知道是哪个抽象类的继承
//工厂模式关注的是创建对象的最终实例
// d、建造者模式(将一个复杂对象的构架层和表现层分离,同样的构建过程可以采用不通展现)(关注船舰对象的细节问题)
/**
* 应聘者建造者
* 参数name : 姓名
* 参数work :期望职位
*/
var Named = function (name) { };
var Work = function (work) { };
Named.prototype.getName = function () { };
work.prototype.getWork = function () { };
var Person = function (name, work) {
//创建应聘者缓存对象
var _person = new Human();
//创建应聘者姓名对象
_person.name = new Named(name);
//创建应聘者期望值为对象
_person.work = new Work(work);
//返回创建的应聘者
return _person;
}
// e、原型模式(用原型实例指向创建对象的类,使得新创建的对象的类共享原型对象的属性以及方法)
//图片轮播
var LoopUmages = function (imgArr, container) {
this.imagesArray = imgArr; //轮播图片数组
this.container = container; //轮播图片容器
this.createImage = function () { }; //创建轮播图片
this.changeImage = function () { }; //切换下一张图片
}
// 最优方式
var LoopUmages = function (imgArr, container) {
this.imagesArray = imgArr; //轮播图片数组
this.container = container; //轮播图片容器
}
LoopUmages.prototype = {
createImage: function () { }; //创建轮播图片
changeImage: function () { }; //切换下一张图片
}
// 实现不同效果而继承后重写实例方法
//上下滑动继承切换类
var SlideLoopImg = function (imgArr, container) {
//构造函数继承图片轮播类
LoopImages.call(this, imgArr, container);
//重写继承的切换下一张图片的方法
this.changeImage = function () {
console.log('SlideLoopImage changeImage function');
}
}
//渐隐继承切换类
var FadeLoopImg = function (imgArr, container, arrow) {
//构造函数继承图片轮播类
LoopImages.call(this, imgArr, container);
//切换箭头私有变量
this.arrow = arrow;
//重写继承的切换下一张图片的方法
this.changeImage = function () {
console.log('FadeLoopImg changeImage function');
}
}
// 属性复制实现对象创建,减少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();
}
// f、单例模式(只允许实例化一次的对象类,也称为单体模式)
//就是为所定义的方法提供一个命名空间(namespace) 如 jqury
var Conf = (function () {
//私有变量 静态变量 习惯大写
var conf = {
MAX_NUM: 100,
MIN_NUM: 1,
COUNT: 1000
}
//返回取值器对象
return {
//取值器的方法
get: function (name) {
return conf[name] ? conf[name] : null;
}
}
})()
//惰性单例模式
var LazySingle = (function () {
//单体实例引用
var _instance = null;
function Single() {
//定义私有属性和方法
return {
publicMethod: function () { },
publicProperty: "1.0"
}
}
//获取单例对象接口
return function () {
//如果未创建单利将创建
if (!_instance) {
_instance = Single();
}
//返回单例
return _instance;
}
})()
}
第二大类、结构型设计模式(将类和对象组合成更复杂的结构)
{
// a、外观模式(为一组复杂的子系统接口提供一个更高级的统一接口)
//添加事件的外观模式实现
function addEvent(dom, type, fn) {
if (dom.addEventListener) {
dom.addEventListener(type, fn, false);//多数浏览器
} else if (dom.attachEvent) {
dom.attachEvent("on" + type, fn);//低版本ie
} else {
dom['on' + type] = fn;//支持on的
}
}
//获取事件对象
var getEvent = function (event) {
//标准浏览器返回event IE返回window.event
return event || window.event;
};
//获取元素
var getTarget = function (event) {
var event = getEvent(event);
//标注浏览器下event.target,IE下event.srcElement
return event.event || event.srcElement;
}
//阻止默认行为
var perventDefault = function (event) {
var event = getEvent(event);
if (event.preventDefault) {
//标准浏览器
event.preventDefault();
} else {
//IE览器
event.returnValue = false;
}
};
// b、适配器模式(将一个类的接口转化成另外一个接口,已满足需求)
// 传参使用
var parmas = {
name: "name",
age: "age",
sex: "sex"
}
// c、代理模式(一个对象不能直接引用另一个对象,所以需要通过代理在这两个对象之间起到中介的作用)
// 图片的src实现统计代理(单向 无返回)
//统计代理
var Count = (function () {
//缓存图片(参考备忘录模式)
var _img = new Image();
//返回统计函数
return function (param) {
//统计请求字符串
var str = "http://www.count.cim/a.gif";
//拼接请求字符串
for (var i = 0 in param) {
str += i + "=" + param[i];
}
//发送统计数据
_img.src = str;
}
})();
//测试用例
Count({ num: 10 });
//scrupt标签代理模式(请求只是单份数据,需要src的url加上标识 服务区获取后保留一份)
//也就是callback的实现(jsonp方案)
//图片预加载也成为虚拟代理模式
// d、装饰者模式(在不改变原对象的基础上,对其拓展属性和方法以满足客户需求)
//装饰者
var decorator = function (input, fn) {
//获取事件源
var input = document.getElementById(input);
//若事件源已绑定事件
if (typeof input.onclick === "function") {
//缓存事件源原有回调函数
var oldClickFn = input.onclick;
//为事件源定义新的事件
input.onclick = function () {
//事件源原有回调函数
oldClickFn();
//执行新增回调函数
fn();
}
} else {
//事件源未绑定事件,直接添加新增事件即可
input.onclick = fn;
}
//做其他事情
}
// PS:与适配器模式的区别是:适配器需要了解原有方法的实现细节,装饰着模式不需要,原有方法原封不动的调用。
// e、桥接模式(解耦)
//抽象
function changeColor(dom, color, bg) {
//设置元素字体颜色
dom.style.color = color;
//设置元素背景颜色
dom.style.background = bg;
}
var spans = document.getElementByTagName("span");
spans[0].onmouseover = function () {
changeColor(this, "red", "#add");
}
// changeColor方法中的dom实质上是事件回调函数中的this,我们相解除他们之间的耦合,就需要一个桥接方法-----匿名回调函数。
// 通过这个函数,获取到this传递到changeColor函数中,即可实现。
//桥接模式就是先抽象提取公共部分,然后将实现与抽象通过桥接方法链接在一起
spans[0].onmouseover = function () {
changeColor(this.getElementByTagName("strong")[0], "red", "#add");
}
// f、组合模式(使得单个对象和组合对象的使用具有一致性)(难点==============)
var News = function () {
//子组件容器
this.children = [];
//当前组件元素
this.element = null;
}
News.prototype = {
init: function () {
throw new Error("请重写你得方法!");
},
add: function () {
throw new Error("请重写你得方法!");
},
getElement: function () {
throw new Error("请重写你得方法!");
}
}
//容器类构造函数
var Container = function (id, parent) {
//构造函数继承父类
News.call(this);
//模块id
this.id = id;
//模块的父容器
this.parent = parent;
//构建方法
this.init();
}
//寄生式继承父类原型方法
inheritPrototype(Container, News);
//构建方法
Container.prototype.init = function () {
this.element = document.createElement("ul");
this.element.id = this.id;
this.element.className = "new-container";
};
//添加子元素方法
Container.prototype.add = function (child) {
//在子元素容器中插入子元素
this.children.push(child);
//插入当前组件元素树中
this.element.appendChild(child.getElement());
return this;
}
//获取当前元素的方法
Container.prototype.getElement = function () {
return this.element;
}
//显示方法
Container.prototype.show = function () {
this.parent.appendChild(this.element);
}
// g、享元模式(运用共享技术有效的支持大量的细粒度的对象)
// 分页模式应用
// 提取公用部分 继承享用 较少内存消耗
}
第三大类、行为型设计模式(将对象之间职责划分或算法抽象)
// a、模板方法模式
// 父类中实现的算法骨架,延迟到子类中实现具体步骤,可以在子类中重新定义算法中某些实现步骤
// 弹框实现
//继承类也可以作为模板类
// b、观察者模式(发布订阅者模式)(重点)(定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合)
//将观察者放在闭包中,当页面加载就立即执行
var Observer =(function(){
//防止消息队列暴漏而被篡改故将消息容器作为静态私有变量保存。
var _messages = {};
return {
//注册信息接口(将订阅者注册的消息推入到消息队列)
regist:function(type,fn){
//如果此消息不存在应该创建一个该消息类型
if(typeof _message[type] === "undefined"){
//将动作推入到消息对应的动作执行队列中
_messages[type] = [fn];
}else{//如果消息存在
//将动作推入到消息对应的动作执行队列中
_messages[type].push(fn);
}
},
//发布信息接口
fire:function(){
//如果该消息没有被注册,则返回
if(!_messages[type]){
return;
}
//定义消息信息
var events = {
type:type, //消息类型
args:args || {} //消息携带数据
},
i=0,
len = _messages[type].length; //消息动作的长度
//遍历消息动作
for(;i<len;i++){
//一次执行注册的消息对应的动作序列
_messages[type][i].call(this,events);
}
},
//移除信息接口
remove:function(){
//如果消息动作队列存在
if(_messages[type] instanceof Array){
//从最后一个消息动作遍历
var i = _messages[type].length-1;
for(;i>=len;i--){
//如果存在该动作消息动作序列中移除相应动作
_messages[type][i] === fn && _messages[type].splice(i,1);
}
}
}
}
})();
//使用
Observer.regist("test",function(e){
console.log(e.type,e.args.msg);
})
Observer.fire("test",{msg:"传递参数"})
// c、状态模式(当对象内部状态发生改变时,会导致行为改变)(减少判断分支)
//d、策略模式:(将定义的一组算法封装起来,使其之间可以替换。封装的算法具有一定独立性,不会随客户端变化而变化)(减少判断分支)
//e、职责链模式:(解决请求发送者和接收者之间的耦合)
//f、命令模式:(将请求和实现解耦并封装成独立对象)
//g、访问者模式(针对对象结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法)(精髓就是call和apply)
function bindIEEvent(dom,type,fn,data){
var data = data || {};
dom.attachEvent("on"+type,function(e){
fn.call(dom,e,data);
})
}
// PS:Object.prototype.toString.call来判断返回的数据类型 把对象转成类数组 可以使用数组方法了
//h、中介者模式(通过中介者对象封装一系列对象之间的交互)类似发布订阅模式
//i、备忘录模式(缓存分页数据)
//j、迭代器模式()
//k、解释器模式()
第四大类、技巧型设计模式(将对象之间职责划分或算法抽象)
//a、链模式(jq return this)
//b、委托模式(多个对象接收并处理同一请求,将他们委托给另一对象统一处理请求)(优化页面的事件绑定)
第五大类、架构型设计模式(将对象之间职责划分或算法抽象)
// a、同步模块模式(分而治之 易于管理代码)
// b、异步模块模式
// c、widget模式
// d、MVC模式
// e、MVP模式
// f、MVVM模式