Skip to content

Latest commit

 

History

History
executable file
·
408 lines (337 loc) · 8.48 KB

面向对象.md

File metadata and controls

executable file
·
408 lines (337 loc) · 8.48 KB

###面向对象

面向对象: 数据结构化,对代码的一种抽象,对外统一提供调用接口的变成思想。 基于原型的面向对象方式中,对象(object)则是依靠构造器(constructor)利用原型(prototype)构造出来的

函数构造器 创建函数对象 var obj = new Function(var1, var2, ..., functionBody()) var1,var2 正常变量 functionBody()自定义函数 构造器构造的对象,效率低,var1 var2顺序在functionBody中不能变


###闭包 闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数) 用途: 1 读取函数内部变量 2 让内部变量保存在内存中 优点: 有利于封装,可以访问局部变量 缺点: 内存占用浪费严重,内存泄漏


#####构造和工厂模式不同 1. 构造方式不会显示创建对象, 将属性赋值给this, 不需要return对象 2. 工厂在方法内部创建Object对象,返回object对象,属性和方法都是赋值给object

原型模式声明对象 test。prototype。。 让所有的实例共享方法


#####原型和原型链 原型:是利用prototype添加属性和方法 原型链:JS在创建对象(不论是普通对象还是函数对象)的时候,都会有一个叫做`__proto__`的内置属性,用于指向创建他的函数对象的原型对象prototype

创建对象三个阶段 var person = function () {} var p = new person() 三个阶段

  1. var p = {} 闯将对象
  2. p.__ptoto__ = person.prototype proto自带的一个属性
  3. 创建对象(初始化对象) p --> person.call(p)

#####原型链继承、构造函数继承、call apply继承
callee 返回正在执行的function对象,function内容 arguments.callee 默认值 正在执行的function对象

《UNIX/LINUX设计哲学》
  • 准则1:小即是美
  • 准则2:让每个程序只做好一件事
  • 准则3:快速建立原型
  • 准则4:舍弃高效率而取可移植性
  • 准则5:采用纯文本来存储数据
  • 准则6:杠杆效应
  • 准则7:使用shell脚本来提高杠杆效应和可移植性
  • 准则8:避免强制性的用户界面
  • 准则9:让每个程序成为过滤器
SOLID五大设计原则
  • S(single) 单一职责原则
  • O(open) 开放封闭原则
  • L 李式置换原则
  • I(interface) 接口独立原则
  • D 依赖导致原则 (依赖于抽象而不依赖于具体)
23种设计模式

1、创建型 2、组合型 3、行为型

  1. 创建型
  • 工厂模式
  • 单例模式
  • 原型模式
  1. 结构型
  • 适配器模式
  • 装饰器模式
  • 代理模式
  • 外观模式
  • 桥接模式
  • 组合模式
  • 享元模式
  1. 行为型
  • 策略模式
  • 模板方式模式
  • 观察者模式
  • 迭代器模式
  • 职责连模式
  • 命令模式
  • 状态模式
工厂模式
class Product{
	constructor(name) {
		this.mame = name
	}
}

class Creator() {
	create(name) {
		return new Product(name)
	}
}

$('div') 和 new $('div')有何区别 React的createElement方法 Vue的异步组件 设计原则验证

  • 构造函数和创建者分离
单例模式
public class SingleObject {
  private SingleObject () {

  }

  private SingleObject instance = null

  public SingleObject getInstance() {
    if (instance == null) {
      instance = new SingleObject ()
    }
    return instance
  }

  public void login(username, password) {
	System.out.println('login')	
  }
}

适配器模式

 class Adaptee{
   specificRequest() {
     return '德国标准接口'
   }
 }

 class Target {
   constructor() {
     this.adaptee = new Adaptee()
   }

   request() {
     let info = this.adaptee.specificRequest()
     return `${info} -> 转接器 -> 中国标准接口`
   }
 }
 
 let target = new Target()
 target.request()
  • 将旧接口和使用者进行分离
  • 符合开放封闭原则

装饰器模式

  • 为对象添加新功能
  • 不改变其原有的接口和功能
class Circle {
  draw() {
    console.log('画一个圆')
  }
}
class Decorator {
  constructor() {
    this.circle = new Circle()
  }

  draw() {
    this.circle.draw()
    this.setRedLine()
  }

  setRedLine() {
    console.log('设置红色边框')
  }
}

let c1 = new Circle()
c1.draw()
console.log('------')
let c2 = new Decorator()
c2.draw()

使用场景ES7 decorator

// 使用方法
@testDec
class Demo{

}
function testDec(target) {
  target.isDec = true
}
console.log(Demo.isDec) // true

// 使用方法2
function testDec(isDecVal) {  // 将变量传入
  return function (target) {  // decorator返回一个函数
    target.isDec = isDecVal
  }
}
@testDec(false)
class Demo{

}
console.log(Demo.isDec)  // false

// 对属性添加readOnly
function readOnly (target, name, descriptor) {
  descriptor.writable = false
  return descriptor
}

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }

  getName() {
    return `${this.name} and ${this.age}`
  }
}

var xiaoming = new Person('xiaoming', '18')
xiaoming.getName()
xiaoming.getName = function () {} // error

// 打印日志
function log(target, name, descriptor) {
  let oldValue = descriptor.value
  descriptor.value = function () {
    console.log('is doing ${name} ', arguments)
    return oldValue.call(this, arguments)
  }
  return descriptor
}

class Math() {

  @log
  add(a, b) {
    return a + b;
  }
}

var obj = new Math()
obj.add(1, 2) // is doing add, 1 , 2
  • 讲现有对象和装饰器分离,两者独立存在
  • 符合开放封闭原则
代理模式
let star = {
  name: 'zhang ming',
  age: 25,
  phone: 'start 111111'
}

let agent = new Proxy(star, {
  get: function (target, key) {
    if (key === 'phone') {
      return 'agent 222222'
    }
    if (key === 'price') {
      return 'agemt 100K'
    }
    return target[key]
  },
  set: function (target, key, val) {
    if (key === 'price') {
      if (val < 120) {
        throw new Error('价格太低')
      } else {
        target.customPrice = val
      }
    }
  }
})

console.log(agent.name)
console.log(agent.name)
console.log(agent.phone)
console.log(agent.price)
agent.price = 130
console.log(agent.customPrice)
  • 适配器模式 vs 代理模式 适配器模式: 提供一个不同的接口(如不同版本的插头) 代理模式:提供一模一样的接口

  • 代理模式 vs 装饰器模式 装饰器模式:扩展功能,原有功能不变且可直接使用 代理模式:显示原有功能,但是经过限制或者阉割之后的

外观模式
  • 为子系统中的一组接口提供一个高层接口
  • 使用者使用这个高层接口
观察者模式
  • 发布&订阅
  • 一对多
class Subject{
  constructor() {
    this.state = 0
    this.notifyArr = []
  }

  setState(state) {
    this.state = state
    this.notifyAll()
  }

  getState() {
    return this.state
  }
  
  notifyAll() {
    this.notifyArr.forEach(notify => {
      notify.update()
    })
  }

  addNotify(fn) {
    this.notify.push(fn)
  }

}

class Observer{
  constructor(name, subject) {
    this.name = name
    this.subject = subject
    this.subject.notifyArr.push(this)
  }

  update() {
    console.log(`${this.name} is notify, state is ${this.subject.getState()}`)
  }
}

var sub1 = new Subject()
var o1 = new Observer('o1', sub1)
var o2 = new Observer('o2', sub1)
var o3 = new Observer('o3', sub1)
sub1.setState(1)
sub1.setState(2)
sub1.setState(3)

使用案例:

  1. JQuery callback
  2. Nodejs 自定义事件 其他场景
  • nodejs处理http请求,多进程通讯
  • vue和React组件生命周期触发
  • vue watch
// nodejs 自定义事件
const EventEmitter = require('events').EventEmitter

const emitter1 = new EventEmitter()

emitter1.on('some', info => {
	console.log('fn1', info)
})

emitter1.on('some', info => {
	console.log('fn2', info)
})

emitter1.emit('some', 'message')

设计原则验证

  • 主题和观察者分离,不是主动触发而是被动监听,两者解耦
  • 符合开放封闭原则
迭代器模式
  • 顺序访问一个集合
  • 使用者无需知道集合的内部结构(封装)

ES6 Iterator为何存在?

  • ES6语法中,有序集合的数据类型意见又很多
  • Array Map Set String TypedArray arguments NodeList
  • 需要有一个统一的遍历接口来遍历所有数据类型
  • (注意,object不是有序集合,可以用Map代替)
  • 以上数据类型,都有[Symbol,iterator]属性
  • 属性值是函数,执行函数返回一个迭代器
  • 这个迭代器就有next方法可以顺序迭代子元素
  • 可运行Array.protptype[Symbol.iterator]来测试