# 六.设计模式
# 1.介绍一下单一职责原则和开放封闭原则
- 单一职责原则:一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因
- 开放封闭原则:核心的思想是软件实体(类、模块、函数等)是可扩展的、但不可修改的。也就是说,对扩展是开放的,而对修改时封闭的
# 2.单例模式
单例模式即一个类只能构造除唯一的实例,单例模式的意义在于共享、唯一,Redux、Vuex
中的 store、JQ 的$或者业务场景中的购物车、登录框都是单例模式的应用
class SingletonLongin{
constructor(name,password){
this.name=name
this.password=password
}
static.getInstance(name,password){
if(!this.instance)this.instance = new SingletonLogin(name,password)
return this.instance
}
}
let obj1=SingletonLogin.getInstance('sss','111')
let obj2=SingletonLogin.getInstance('qqq','1111')
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 3.工厂模式
工厂模式即对创建对象逻辑的封装,或者可以理解为对 new 的封装,这种封装就像创建对象的工厂,故名工厂模式。工厂模式常见于大型项目,比如 JQ 的$对象,我们创建选择器对象时之所以没有new selector就是因为$()已经是一个工厂方法,其他例子如React.createElement()
、Vue.component()
都是工厂模式的实现。工厂模式有多种:简单工厂模式,工厂方法模式,抽象工厂模式
,这里只以简单工厂模式为例
class User {
constructor(name, auth) {
this.name = name
this.auth = auth
}
}
class UserFactory {
static createUser(name, auth) {
if (auth === "admin") new User(name, 1)
if (auth === "user") new User(name, 2)
}
}
const admin = UserFactory.createUser("asdf", "1212")
const user = UserFactory.createUser("asdfas", "23423")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 4.观察者模式
观察者模式概念很简单:观察者监听被观察者的变化,被观察者发生改变时,通知所有的观察者。观察者模式被广泛用于监听事件的实现
class Observer {
constructor(fn) {
this.update = fn
}
}
class Subject {
constructor() {
this.observers = []
}
addObserver(observer) {
this.observers.push(observer)
}
notify() {
this.observers.forEach(observer => observer.update())
}
}
var subject = new Subject()
cosnt update = ()=>{console.log('通知')}
var obj1 = new Observer(update)
var obj2 = new Observer(update)
subject.addObserver(obj1)
subject.addObserver(obj2)
subject.notify()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 5.装饰器模式
装饰器模式,可以理解为对类的一个包装,动态的拓展类的功能,ES7装饰器
语法以及 React 中的高阶组件
(HoC)都是这一模式的实现。react-redux 的 connect()也运用了装饰器模式,这里以 ES7 装饰器为例:
function info(target){
target.prototype.name='展示'
target.prototype.age =10
}
@inifo
class Man()
let man = new Man()
man.name
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 6.适配器模式
适配器模式,将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作
class Adaptee {
test() {
return "旧接口"
}
}
class Target {
constructor() {
this.adaptee = new Adaptee()
}
test() {
let info = this.adaptee.test()
return `适配${info}`
}
}
let target = new Target()
console.log(target.test())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 7.代理模式
代理模式,为一个对象找一个替代对象,以便对原对象进行访问。
const idol = {
name: "1212",
phone: 1000,
price: 100000,
}
const agent = new Proxy(idol, {
get: function (target) {
return "经纪人电话1000"
},
set: function (target, key, value) {
if (key === "price") {
if (value < target.price) throw new Error("报价过低")
target.price = value
}
},
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 7. 什么是原型链
- 对于 object 来说,可以通过proto找到一个原型对象,在该对象中定义了很多函数让我们来使用
- 原型链是一种机制,指的是 javascript 每个对象包括原型对象都有一个内置proto属性指向创建它的函数对象的原型对象,即 prototype 属性
- 函数的原型链对象 constructor 默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针proto;该指针是指向上一层的原型对象,而上一层的原型对象的结构依然类似;因此可以利用proto一直指向 object 的原型对象上,而 object 原型对象用 object.prototype=null 表示原型链顶端。如此形成了 js 的原型链继承。同时所有的 js 对象都有 object 的基本方法。
# 8. 类的创建和继承
- 1.原型链继承
- 2.构造函数继承
- 3.组合继承
- 4.原型式继承
- 5.寄生式继承
- 6.寄生组合继承
- 7.混合继承
- 8.es6 继承
# 1·原型链继承
function Parent() {
this.parentName = "parent"
}
Parent.portotype.getParentName = function () {
return this.parentName + 1
}
function Child() {
this.name = "child"
}
Child.prototype = new Parent()
Child.prototype.getChildName = function () {
return this.name + 1
}
var child = new Child()
console.log(child.getParentName())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.构造函数继承
function Parent() {
this.parentName = "parent"
}
Parent.prototype.getParentName = function () {
return this.parentName + 1
}
function Child() {
this.name = "child"
Parent.call(this)
}
Child.prototype.getChildName = function () {
return this.name + 1
}
var child = new Child()
console.log(child.parentName)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.组合继承
function Parent() {
this.parentName = "parent"
}
Parent.prototype.getParentName = function () {
return this.parentName + 1
}
function Child() {
this.name = "child"
Parent.call(this)
}
Child.prototype = new Parent()
Child.prototype.getChildName = function () {
return this.name + 1
}
var child = new Child()
console.log(child.getParentName())
console.log(child.parentName)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 4.原型式继承
function Parent() {
this.parentName = "parent"
}
Parent.prototype.getParentName = function () {
return this.parentName + 1
}
function object(obj) {
function F() {}
F.prototype = obj
return new F()
}
var child = object(new Parent())
child.childName = "child"
child.getChildName = function () {
this.childName + 1
}
console.log(child.getChildName())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 5.寄生式继承
function Parent() {
this.parentName = "parent"
}
Parent.portotype.getParentName = function () {
return this.parentName + 1
}
function createAnother(original) {
var clone = Object(original)
clone.childName = "child"
clone.getChildName = function () {
return this.childName + 1
}
return clone
}
var child = createAnother(new Parent())
child.prototype = new Parent()
console.log(child.parentName)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 6.寄生组合继承
function inheritPrototype(c, p) {
var prototype = Object.create(p.ptototype)
prototype.constructor = c
c.prototype = prototype
}
function Parent() {
this.parentName = "parent"
}
Parent.prototype.getParentName = function () {
return this.parentName + 1
}
function Child() {
this.childName = "child"
Parent.call(this)
}
inheritPrototype(Child, Parent)
Child.prototype.getChildName = function () {
return this.childName + 1
}
var child = new Child()
console.log(child.parentName)
console.log(child.getParentName())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 7.混合式继承
function Parent() {
this.parentName = "parent"
}
Parent.portotype.getParentName = function () {
return this.parentName + 1
}
function Child() {
this.name = "child"
}
Child.prototype.getChildName = function () {
return this.name + 1
}
function MyClass() {
Parent.call(this)
Child.call(this)
}
MyClass.prototype = Object.create(Parent.prototype)
Object.assign(MyClass.prototype, Child.prototype)
MyClass.prototype.constructor = MyClass
var child = new MyClass()
console.log(child.getParentName())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 8.es6 中继承
class Parent {
constructor() {
this.parentName = "parent"
}
getParentName() {
return this.parentName + 1
}
}
class Child extends Parent {
constructor() {
super()
this.childName = "child"
}
getChildName() {
return this.childName + 1
}
}
var child = new Child()
console.log(child.getChildName())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1.模拟实现 new
function _new(fn, args) {
var obj = Object.create(fn.prototype)
var result = obj.apply(fn, args)
return typeof result === "object" && result !== null ? result : object
}
1
2
3
4
5
2
3
4
5
# 2.es5 如何实现继承
- 原型链继承
- 构造函数继承
- 组合式继承
- 寄生组合继承
# 1. 观察者模式
- 在软件开发设计找那个是一个对象(subject),维护一系列依赖他的对象(observer),当任何状态发生改变自动通知他们。强依赖关系
- 简答理解:数据发生改变是,对应的处理函数酒瓯会自动执行。一个 subjet,用来维护 observers,为某些 event 来通知(notify)观察者
# 2.发布-订阅者和观察者模式的区别
它定义了一种一对多的关系,可以使多个观察者对象对一个主体对象进行监听,当这个主题对象发生改变时,依赖的所有对象都会被通知到
两者的区别:
- 1.观察者模式中,观察者知道 subject,两者是相关联的,而发布订阅者只有通过信息代理进行通信
- 2.在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反
- 3.观察者大部分是同步的,比如事件的触发,subject 就会调用观察者的方法,而发布订阅者大多数是异步的
- 4.观察者模式需要在单个应用程序地址空间中实现,而发布订阅者更像交叉应用模式
# 常见的设计模式
- 工厂模式
- 单例模式
- 适配器模式
- 装饰器
- 代理模式
- 发布-订阅模式
- 外观模式