资讯专栏INFORMATION COLUMN

JavaScript 设计模式 一些笔记

paulli3 / 1378人阅读

摘要:如果非要重写父类的方法,比较通用的做法是原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖聚合,组合等关系代替。里氏替换原则通俗的来讲就是子类可以扩展父类的功能,但不能改变父类原有的功能。一有限状态机状态总数是有限的。

设计模式 抽象类 抽象类的表现

不能被实例,只能被继承

最少有一个抽象方法(多态的具体体现)

// 汽车抽象类,当使用其实例对象的方法时会抛出错误
var Car = function() {};
Car.prototype = {
  getPrice: function() {
    return new Error("抽象方法getPrice不能调用。");
  },
  getSpeed: function() {
    return new Error("抽象方法getSpeed不能调用。");
  }
};

上面Car类其实什么都没有做,但用原型的方法还会直接报错,这一特点非常有必要,因为总会有一些子类去继承父类,这些父类经常会去定义一些必要的方法,却没有具体的实现.

一旦子类创建了一个对象,但是子类没有重写父类的方法而被调用,就会直接报错,这个对大型项目中对子类的约束是非常有必要的,代码页更加清晰

单一职责原则
...
里氏替换原则

子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法
继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。

function Foo(){
    this.aa="sdf";
}

Foo.prototype.func1 = function(a,b){
    return a-b;
};


function Sub(){

}

Sub.prototype = new Foo();

var demo = new Sub();
console.log("100-50="+demo.func1(100,50));

//运行结果:
//100-50=50


//后来,我们需要增加一个新的功能:完成两数相加,然后再与100求和,由类B来负责。即类B需要完成两个功能:

function Sub1 (){
}

Sub1.prototype = new Foo();


Sub1.prototype.func1 = function(a,b){
    return a+b;
};

Sub1.prototype.func2 = function(a,b){
    return this.func1(a,b)+100;
};

var demo1 = new Sub1();
console.log("100-50="+demo1.func2(100,50))

//运行结果:
//100-50=250
我们发现原本运行正常的相减功能发生了错误。原因就是类Sub1在给方法起名时无意中重写了父类的方法,造成所有运行相减功能的代码全部调用了类Sub1重写后的方法,造成原本运行正常的功能出现了错误。在本例中,引用基类Foo完成的功能,换成子类Sub1之后,发生了异常。在实际编程中,我们常常会通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的几率非常大。如果非要重写父类的方法,比较通用的做法是:原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖、聚合,组合等关系代替。

里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
子类中可以增加自己特有的方法。
当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
看上去很不可思议,因为我们会发现在自己编程中常常会违反里氏替换原则,程序照样跑的好好的。所以大家都会产生这样的疑问,假如我非要不遵循里氏替换原则会有什么后果?
后果就是:你写的代码出问题的几率将会大大增加。

参考文档:http://blog.csdn.net/zhengzhb...

开闭原则
function Foo(){

}

Foo.prototype.getPerson = function(name){
    if(name==="tom"){
        return {
            name:"tom",
            age:"20"
        }
    }else if(name==="jack"){
        return {
            name:"tom",
            age:"20",
            sex:"boy"
        }
    }
}

console.log(new Foo().getPerson("tom"));

//这个时候 如果我要获取名为lily这个人的属性,就需要更改getPerson,这样所有调用该接口的对象都会受到影响,这个时候我们如何来重构

function Foo(){

}

Foo.prototype.personInfo = function(){};//写一个抽象方法

Foo.prototype.getPerson = function(){
    return this.personInfo();
};


var a = new Foo();
a.personInfo=function(){
    return {
        name:"lily",
        age:20,
        sex:"girl"
    }
};

console.log(a.getPerson());
状态模式
状态模式(State)允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类。

状态模式的使用场景也特别明确,有如下两点:
一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。(有些对象通常会有好几个状态,在每个状态都只可以做当前状态才可以做的事情,而不能做其它状态能做的事儿)
一个操作中含有大量的分支语句,而且这些分支语句依赖于该对象的状态。状态通常为一个或多个枚举常量的表示。

一、有限状态机

状态总数(state)是有限的。
任一时刻,只处在一种状态之中。
某种条件下,会从一种状态转变(transition)到另一种状态。
// 状态机
var FSM = {
  off: {
    buttonWasPressed: function() {
      console.log("关灯");
      this.button.innerHTML = "下一次按我是开灯";   // 这是Light上的属性!!!
      this.currState = FSM.on;            // 这是Light上的属性!!!
    }
  },
  on: {
    buttonWasPressed: function() {
      console.log("开灯");
      this.button.innerHTML = "下一次按我是关灯";
      this.currState = FSM.off;
    }
  },
};
 
var Light = function() {
  this.currState = FSM.off;  // 设置当前状态
  this.button = null;
};
 
Light.prototype.init = function() {
  var button = document.createElement("button");
  self = this;
 
  button.innerHTML = "已关灯";
  this.button = document.body.appendChild(button);
  this.button.onclick = function() {
    // 请求委托给FSM状态机
    self.currState.buttonWasPressed.call(self);
  }
 
}
 
var light = new Light();
light.init();

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95708.html

相关文章

  • JavaScript 设计模式与开发实践读书笔记

    摘要:设计模式与开发实践读书笔记最近利用碎片时间在上面阅读设计模式与开发实践读书这本书,刚开始阅读前两章内容,和大家分享下我觉得可以在项目中用的上的一些笔记。事件绑定暂时这么多,以后会不定期更新一些关于我读这本书的笔记内容 JavaScript 设计模式与开发实践读书笔记 最近利用碎片时间在 Kindle 上面阅读《JavaScript 设计模式与开发实践读书》这本书,刚开始阅读前两章内容,...

    FingerLiu 评论0 收藏0
  • JS代理模式JavaScript设计模式与开发实践》阅读笔记

    摘要:保护代理和虚拟代理保护代理当有许多需求要向某对象发出一些请求时,可以设置保护代理,通过一些条件判断对请求进行过滤。虚拟代理在程序中可以能有一些代价昂贵的操作。而虚拟代理是最常用的一种代理模式。 代理模式 代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。 保护代理和虚拟代理 保护代理:当有许多需求要向某对象发出一些请求时,可以设置保护代理,通过一些条件判断对请求进行过滤。...

    mist14 评论0 收藏0
  • Javascript模式 阅读笔记-1.函数模式

    摘要:模式阅读笔记第一部分函数模式总的来说模式是一本力荐的进阶书书里面涉及了很多在学习过程中会碰到的坑然后提供了很不错的解决方法虽然很多人吐槽这本书的翻译但是糟糕的翻译还是无法掩盖这是一本好书的事实因此这里我会结合书上的知识和我的理解来写一些 Javascript模式 阅读笔记-第一部分-函数模式 总的来说,javascript模式是一本力荐的js进阶书,书里面涉及了很多在学习javascr...

    PiscesYE 评论0 收藏0
  • 基本方法笔记 - 收藏集 - 掘金

    摘要:探讨判断横竖屏的最佳实现前端掘金在移动端,判断横竖屏的场景并不少见,比如根据横竖屏以不同的样式来适配,抑或是提醒用户切换为竖屏以保持良好的用户体验。 探讨判断横竖屏的最佳实现 - 前端 - 掘金在移动端,判断横竖屏的场景并不少见,比如根据横竖屏以不同的样式来适配,抑或是提醒用户切换为竖屏以保持良好的用户体验。 判断横竖屏的实现方法多种多样,本文就此来探讨下目前有哪些实现方法以及其中的优...

    maochunguang 评论0 收藏0
  • javascript高级程序设计笔记:内存与执行环境

    摘要:因此,所有在方法中定义的变量都是放在栈内存中的当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用因为对象的创建成本通常较大,这个运行时数据区就是堆内存。 上一篇:《javascript高级程序设计》笔记:继承近几篇博客都会围绕着图中的知识点展开 showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...

    fuyi501 评论0 收藏0
  • JS策略模式JavaScript设计模式与开发实践》阅读笔记

    摘要:策略模式可以避免代码中的多重判断条件。策略模式在程序中或多或少的增加了策略类。此文仅记录本人阅读设计模式与开发实践这个本时的感受,感谢作者曾探写出这么好的一本书。设计模式中很重要的一点就是将不变和变分离出来。参考设计模式与开发实践曾探 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且是它们可以相互替换。 策略模式可以避免代码中的多重判断条件。 策略模式很好的体现了开放-...

    Amos 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<