设计模式与实践

2019-11-24  本文已影响0人  fanstastic

多态:同一操作作用于不同对象上面,可以产生不同的解释和不同的执行结果。给不同的对象发送同一个消息,这些对象会根据消息给出不同的反馈。

首先我们把不变的部分抽离出来,就是所有动物都会发出叫声

let makeSound = (animal) => { animal.sound() }
var Duck = function () {}
Duck.prototype.sound = () => { console.log(ggg) }
class Duck {
  sound () {
    
  }
}
public class Duck {
 public void makeSound() {
   // ggg
 }
}  
public class AnimalSound {
 public void makeSound( Duck duck ) {
   duck.makeSound();
 }
}

此时,我们只能让鸭叫,为了解决这种问题,静态类型的面向对象语言可以设计为向上转型;当给一个类变量赋值时,这个变量的类型既可以这个类本身,也可以是使用这个类的超类。
使用继承得到多态效果,是让对象表现出多态性的最常用手段。
我们首先创建一个Animal抽象类,再分别让Duck和chicken都继承自Animal抽象类
js的根对象是Object.prototype

当对象a需要继承对象b的能力时,可以让a的构造器的原型指向对象b,达到继承的效果

var obj = {}
function A() {}
A.prototype = obj

当我们期望得到一个类继承另一个类的时候的时候

function A () {}
A.prototype = { name: 'hhh' }

function B() {}
B.prototype = new A()

实例在查找属性时,先查找实例本身,在查找实例的构造函数,在查找构造函数的原型继承的构造函数的实例。。。。
原型链并不是无限长,终点是Object.prototype = undefined
通过Object.create(null)可以创建一个没有原型对象的对象

this, call, apply

js的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。
func.apply(null, [1, 2, ,3])
func.call(null, 1, 2, 3) 改变函数里的this,后续的参数是func执行时的参数
第一个参数代表this在func中的指向
如果是null,浏览器默认指向null

document.getElementById = () => {}
func.prototype.bind = function(context) {
  return () => {
      this.call(context, ...arguments)
  }
}

在bind函数内部,先把func函数引用保存,然后返回一个新的函数,执行func的时候,实际上执行的是新函数。在执行的内部才是执行原来的func函数,并且指定context对象为func函数体内的this。

  1. 借用构造函数
var A = function(name) {
  this.name = name
}

var B = function() {
  
}
  1. 函数可以作为参数被传递
  2. 函数可以作为返回值输出
var getString = function(fn) {
  var ret;
  return function() {
      return ret || (ret = fn.apply(this,arguments))
  }
}
Function.prototypr.before = function(beforefn) {
  var _self = this; // 这_sel里的this指向调用的对象
  return function() {
     beforeFn()
      return _self.apply(this)
  }
}
var func = function() {
  console.log(2)
}

func = func.before(function() {
    console.log(1)
}).after(function() { console.log(3) })

func()

调用before的是func这个函数

curry

let cost = (function(){
  var args = []
  return () => {
    
  }
})()
var currying = function(fn) {
  var args = []
  return fucntion() {
      // 根据参数判断是求值还是保存值 
  }
}  
Function.prototype.uncurry = function() {
  var self = this;
  return function() {
    var obj = Array.prototype.shift.call(arguments)
    return self.apply(obj)
  }
}
var throttle = (fn, interval) => {
  var self = fn;
  timer, // 用一个标识标识定时器是否结束
  firsttime
  return (...args) => {
     if (firsttime) {
          self()
          return firsttime = false
      }   
      // 如果定时器存在,说明上一次的执行还没有结束
      if (timer) {
          return false
      }
      timer = setTimeout (() => {
           // 每次定时器一执行就清除当前定时器
          clearTimeout(timer)
          timer = null;
          
      }, interval || 500)
  } 
}
var timeChunk  = (ary, fn, count) => {
  var obj, t;
  var len=ary.length
  var start = () => {  }
  return () => {
    t = serInterval(() => {
        if (!ary.length) { claearInterval(t) }
    })
  }
}
// 通过闭包保存单例标识
  function A (name) { this.name = name }
    A.prototype.getIns = (() => { var ins = null;return (name) => {
         if (!ins) { ins = new A(name) }   return ins
    }})()
var Create = (() => {
  var instance;
  // 构造函数执行的时候,如果存在实例,则直接返回实例
  var Create = function (html) {
    if (instance) return instance
    this.html = html
    this.init = ()
    return instance = this
  }
  Create.prototype.init = () => { var div = document.createElement('div')
      div.innerHTML = this.html
      document.body.appendChild(div)    
 }
  return  Create
})()

var a = new Create('sc')
var b = new Create('sv')

var proxyCreate = (() => { var instance = null; return (html) => {
      van instance;
      if (!instance) instance = new Create(html)
      return instance
} })()
var performanceS = function() {}
performanceS.prototype.calculate  = function(salary) {
    return salary * 4;
}

var performanceA = function() {}
performanceS.prototype.calculate  = function(salary) {
    return salary * 3;
}

var performanceB = function() {}
performanceS.prototype.calculate  = function(salary) {
    return salary * 2;
}

vae Bonus = function () {
  this.salary = null;
  this.stratery = null;
}

Bonus.prototype.setSalary = function(salary) { this.salary = salary }
Bonus.prototype.setStratery = function(stratery) { this.stratery = stratery }
Bonus.prototype.getBonus = function() { return this.stratery.calculate(this.salary) }

通过使用策略模式重构的代码,我们消除了源程序中大片的条件分支语句。

var strategies = {
  isNoneEmpty: (value, errorMsg) => { if (!value) return errorMsg},
  minLength: () => 
}
 var validataFunc = () => {
  var validator = new Validator()
  validator.add(regis.userName, 'isNoneEmpty', 'userName不能为空')
  var errorMsg = validator.start()
  return errorMsg
}

当我们往validator对象里添加完一系列的校验规则之后,通过start方法来启动校验,

var Validator = function(){ this.cache = [] }
Validator.prototype.add = (dom, rule, errorMsg) => {
   var ary = rule
}
Validator.prototype.start = () => {
  for (var i=0, validatorFunc; )
}
var Flower = function(){}
var xiaoming = {
  sendFlower: function(target) {
      var flower = new Flower()
      target.receiveFlower(flower)
   }
}
var B = {
  receiveFlower: (flower) => {
    A.listenGoodMood(() => {
      A.receiveFlower(flower)
    })
  }
}
xiaoming.sendFlower(B)
  1. 用户可以放心的使用代理,它只关心是否能得到想要的结果。
  2. 在任何使用本体的地方都可以替换成使用代理

在java等语言中,代理和本体都需要显示的实现同一个接口,一方面接口保证了它们会使用同样的方法,另一方面,通过接口向上转型,避开编译器的类型检查,代理和本体将来可以被替换使用。

let cache = []
let minConsole = {
  log: (...args) => {cache.push(() => {  })}
}

当用户按下f2的时候

上一篇 下一篇

猜你喜欢

热点阅读