设计模式的目的
是为了优化代码, 优化内存, 代码复用, 高效的解决一些问题, 总结的一些编程经验.
单例模式
应用场景: 创建重复度较高的对象时. 为了优化代码, 节省内存. 使用单例, 判断, 对象是否已经生成, 如果生成了, 新的 new 就返回已经有的对象.
经典的实现方式是, 创建一个类, 或者一个函数, 这个类或函数包含一个方法, 这个方法在没有对象存在的情况下, 将会创建一个新的实例对象. 如果对象存在, 这个方法只是返回这个对象的引用.
- var Single = (function(){
- var instance;
- function init() {
- // 定义私有方法和属性
- // 操作逻辑
- return {
- // 定义公共方法和属性
- };
- }
- return {
- // 获取实例
- getInstance:function(){
- if(!instance){
- instance = init();
- }
- return instance;
- }
- }
- })();// 这里必须使用匿名执行函数. 还不知道为什么
- var obj1 = Single.getInstance();
- var obj2 = Single.getInstance();
- console.log(obj1 === obj2);
工厂模式 ----
多个实例相似多很高, 可以封装一个类, 通过传参产生不同的实例.
一对多的关系, 一个工厂, 一个类, 传入不同的参数, 得到不同的实例.
工厂模式是我们最常用的实例化对象模式了, 是用工厂方法代替 new 操作的一种模式.
因为工厂模式就相当于创建实例对象的 new, 我们经常要根据类 Class 生成实例对象, 如 A a=new A() 工厂模式也是用来创建实例对象的, 所以以后 new 时就要多个心眼, 是否可以考虑使用工厂模式, 虽然这样做, 可能多做一些工作, 但会给你系统带来更大的可扩展性和尽量少的修改量.
- function Animal(opts){
- var obj = new Object();
- obj.color = opts.color;
- obj.name= opts.name;
- obj.getInfo = function(){
- return '名称:'+ obj.name+', 颜色:'+ obj.color;
- }
- return obj;
- }
- var cat = Animal({name: '波斯猫', color: '白色'});
- cat.getInfo();
- var dog = Animal({name: '癞皮狗', color: '黑色'});
- dog.getInfo();
- // 这里为什么. 只能打印出来一个实例的数据呢?
构造函数模式
ECMAScript 中的构造函数可用来创建特定类型的对象, 像 Array 和 Object 这样的原生构造函数, 在运行时会自动出现在执行环境中. 此外, 也可以创建自定义的构造函数, 从而定义自定义对象的属性和方法. 使用构造函数的方法, 既解决了重复实例化的问题, 又解决了对象识别的问题.
- function Animal(name, color){
- this.name = name;
- this.color = color;
- this.getName = function(){
- return this.name;
- }
- }
- // 实例一个对象
- var cat = new Animal('猫', '白色');
- console.log( cat.getName() );
观察者模式 | 订阅 / 发布模式 (subscribe & publish) 两者有差别, 观察者模式是基础模式, 订阅发布模式, 进行了小小的升级. 还是一对多的关系. 一就是
text 属性变化了, set 方法触发了, 但是文本节点的内容没有变化. 如何才能让同样绑定到 text 的文本节点也同步变化呢? 这里又有一个知识点: 订阅发布模式.
订阅发布模式又称为观察者模式, 定义了一种一对多的关系, 让多个观察者同时监听某一个主题对象, 这个主题对象的状态发生改变时就会通知所有的观察者对象.
发布者发出通知 => 主题对象收到通知并推送给订阅者 => 订阅者执行相应的操作.
- // 一个发布者 publisher, 功能就是负责发布消息 - publish
- var pub = {
- publish: function () {
- dep.notify();
- }
- }
- // 多个订阅者 subscribers, 在发布者发布消息之后执行函数
- var sub1 = {
- update: function () {
- console.log(1);
- }
- }
- var sub2 = {
- update: function () {
- console.log(2);
- }
- }
- var sub3 = {
- update: function () {
- console.log(3);
- }
- }
- // 一个主题对象
- function Dep() {
- this.subs = [sub1, sub2, sub3];
- }
- Dep.prototype.notify = function () {
- this.subs.forEach(function (sub) {
- sub.update();
- });
- }
- // 发布者发布消息, 主题对象执行 notify 方法, 进而触发订阅者执行 Update 方法
- var dep = new Dep();
- pub.publish();
发布者负责发布消息, 订阅者负责接收接收消息, 而最重要的是主题对象, 他需要记录所有的订阅这特消息的人, 然后负责吧发布的消息通知给哪些订阅了消息的人.
组合模式 ----- 一对多的关系, 一个类或者方法, 批量处理所有的事.
组合模式 描述了一组对象可像单个对象一样的对待.
这允许我们能统一的处理单个对象或多个对象. 这意味着无论是一个对象还是一千个对象我们都能以同样的行为来处理.
在 jQuery 中, 当我们在一个节点或多个节点上应用方法时, 我们都能以相同的方式来选择并返回 jQuery 对象.
下面这个演示我们将使用 jQuery 的选择器. 对单一元素 (比如拥有唯一 ID 的元素) 或拥有相同标签或 Class 的一组元素添加名为 active 的 class, 对待它们使用上并无不同:
- // 单一节点
- $( "#singleItem" ).addClass( "active" );
- $( "#container" ).addClass( "active" );
- // 一组节点
- $( "div" ).addClass( "active" );
- $( ".item" ).addClass( "active" );
- $( "input" ).addClass( "active" );
jQuery 的 addClass() 实现中直接使用原生的 for 循环, jQuery 的 jQuery.each(),jQuery.fn.each 来迭代一个集合以达到能同时处理一个或一组元素的目的. 请看下面的例子:
- addClass: function( value ) {
- var classNames, i, l, elem,
- setClass, c, cl;
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).addClass( value.call(this, j, this.className) );
- });
- }
- if ( value && typeof value === "string" ) {
- classNames = value.split( rspace );
- for ( i = 0, l = this.length; i < l; i++ ) {
- elem = this[ i ];
- if ( elem.nodeType === 1 ) {
- if ( !elem.className && classNames.length === 1 ) {
- elem.className = value;
- } else {
- setClass = ""+ elem.className +" ";
- for ( c = 0, cl = classNames.length; c < cl; c++ ) {
- if ( !~setClass.indexOf( ""+ classNames[ c ] +" " ) ) {
- setClass += classNames[ c ] + " ";
- }
- }
- elem.className = jQuery.trim( setClass );
- }
- }
- }
- }
- return this;
- }
总结一下, 23 种分类模式的, 太坑了, 缺少具体的分类标准, 而且, 模式的名字起的也是乱七八糟, 不能望文生义. 这是很恶心的地方. 还需要多多接触不同的项目, 来学习他.
来源: http://www.bubuko.com/infodetail-3433833.html