首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

前端必须知道的设计模式

  • 25-04-19 11:40
  • 3853
  • 5939
juejin.cn

前言:我想作为前端开发从业人员,都大致听说过什么是设计模式,之前看到一本书的名字就叫JavaScript设计模式。

ps:书籍资料可以自行搜索pdf文档查看

什么是设计模式

设计模式是软件设计中常见问题的解决方案,这些模式易于重复使用且富有表现力。

维基百科介绍: 在软件工程中,软件设计模式是针对软件设计中给定上下文中常见问题的通用可重复使用解决方案。它不是可以直接转换为源代码或机器代码的完成设计。它是一种如何解决问题的描述或模板,可用于许多不同情况。

设计模式的类型

  1. 创建型
  2. 结构型
  3. 行为

1.创造-建型设计模式

顾名思义创建型模式将创建对象,而不是直接实例化一个对象

维基百科介绍:在软件工程中,创建型设计模式是处理对象创建机制的设计模式,尝试以适合情况的方式创建对象。对象创建的基本形式可能会导致设计问题或增加设计的复杂性。创建型设计模式通过某种方式控制此对象创建来解决此问题。

1.1 工厂方法:它用于创建单个对象接口,并让子类决定实例化哪个类。

示例如下:有一个类点,创建一个笛卡尔点和一个极点,将定义一个点工厂类实现

js
代码解读
复制代码
CoordinateSystem = { CARTESIAN: 0, POLAR: 1, } // 一个点类 class Point { constructor(x, y) { this.x = x this.y = y } // 重新定义set方法(set,get方法) static get factory() { return new PointFactory(); } }

接下来我们创建Point Factory,并使用我们的工厂

js
代码解读
复制代码
class PointFactory { static new CartesianPoint(x, y) { return new Point(x, y) } static newPolarPoint(rho, theta) { return new Point(rho + Math.cos(theta), rho * Math.sin(theta)) } } // 如何去使用 let point1 = PointFactory.newPolarPoint(5, Math.PI / 2) let point2 = PointFactoty.newCartianPoint(5, 6) console.log(point1, point2)

1.2 抽象工厂:它可以创建家族或组,而不指定它们的具体类型。

维基百科介绍:抽象工厂模式提供了一种方法类封装一组居勇共同主题的单个工厂,而无需指定它们的具体类。

示例如下:使用饮料和饮料制作机原理实现

饮料制作

js
代码解读
复制代码
class Drink { consume() {} } // 继承类重写consume class Tea extends Drink { consume() { console.log('这是一杯茶') } } class Coffee extends Drink { consume() { console.log('这是一杯咖啡') } }

制作饮料工厂

js
代码解读
复制代码
class DrinkFactory { prepare(amount) } class TeaFactory extends DrinkFactory { makeTea() { console.log('Tea Created') return new Tea(); } } class CoffeeFactory extends DrinkFactory { makeCoffee() { console.log('Coffee Created') return new Coffee(); } } // 如何使用 // 实例化工厂函数 let teaDrinkFactory = new TeaFactory() // 调用工厂函数中的方法制作茶 let tea = teaDrinkFactory.makeTea() // 输出 tea.consume()

1.3 建造者:从简单对象构造复杂对象

维基百科介绍:建造者模式是一种设计模式,为面向对象编程中的各种对象创建问题提供灵活的解决方案。

例子:使用存储个人信息的人员类作为示例

js
代码解读
复制代码
class Person { constructor() { this.streetAddress = this.postcode = this.city = '' this.companyName = this.position = '' this.annualIncome = 0 } toString() { return ( `生活在 ${this.streetAddress}, ${this.city}, ${this.postCode},工作在${this.companyName}是一个${this.position}收入${this.annualIncome} ) } }

现在创建人员生成器,人员职务生成器,人员地址生成器

js
代码解读
复制代码
class PersonBuilder { constructor(person = new Person()) { this.person = person } get lives() { return new PersonAddressBuilder(); } get works() { return new PersonJobBuilder(); } build() { return this.person } } // 创建人员工作函数 class PersonJobBuilder extends PersonBuilder { constructor(person) { super(person); } at(companyName) { this.person.companyName = companyName return this } asA(position) { this.person.position = position return this } earning(annualIncome) { this.person.annualIncome = annualIncome return this } } // 创建人员地址生成器 class PersonAddressBuilder extends PersonBuilder { constructor(person) { super(person); } at(streetAddress) { this.person.streetAddress = streetAddress return this } withPostcode(postcode) { this.person.postcode = postcode return this } in(city) { this.person.city = city return this } }

使用

js
代码解读
复制代码
let personBuilder = new PersonBuilder() let person = personBuilder.lives .at('重庆') .in('') .withPostCode('9527') .works .at('重庆') asA('') .earning('1000000') .build() console.log(person.toString())

1.4 原型:它从现有对象重新创建对象。

维基百科介绍:原型模式是软件开发中的依照那个创建型设计模式,当要创建的对象类型由原型实例决定,会使用原型模式,该实例会被克隆以生成新对象。

js
代码解读
复制代码
class Car { constructor(name, model) { this.name = name this.model = model } SetName(name) { console.log(`${name}`) } clone() { return new Car(this.name, this.model) } } let car = new Car() car.SetName('奥迪') // 使用现有对象创建新对象 let car2 = car.clone() car2.SetName('宝马')

1.5 单例:确保为特定的类只创建一个对象。

维基百科介绍:在软件工程中,单例模式是一种软件设计模式,它将类的实例化限制为一个单一的实例,当只需要一个对象来协调整个系统的操作时,就很有用。

创建一个单例类

js
代码解读
复制代码
class Singleton { constructor() { const instance = this.constructor.instance if (instance) { return instance } this.constructor.instance = this } say() { console.log('Saying...') } } let s1 = new Singleton let s2 = new Singleton console.log('两者相等吗' + (s1 === s2)) // true s1.say()

2. 结构设计模式

这些模式涉及类和对象组合,它们使用集成来组合接口

维基百科介绍:在软件工程中,结构设计模式是通过识别实现实体之间关系的简单方法来简化设计的设计模式。

2.1 适配器

这种模式允许具有不兼容接口的类通过将其自己的接口包装在现有的类周围一起工作。

维基百科介绍:在软件工程中,适配器模式是一种软件设计模式,允许将现有类的接口用作另外一个接口,它通常用于使现有类与其他类协同工作而无需修改源码。

例子:

js
代码解读
复制代码
class Calculator1 { constructor() { this.operations = function(value1, value2, operation) { switch (operation) { case 'add': return value1 + value2 case 'sub': return value1 - value2 } } } } class Calculator2 { constructor() { this.add = function(value1, value2) { return value1 + value2 } this.sub = function(value1, value2) { return value1 - value2 } } } // 添加适配器 class CalcAdapter { constructor() { const cal2 = new Calculator2() this.operation = function(value1, value2, operation) { switch (operation) { case 'add': return cal2.add(value1, value2) case 'sub': return cal2.sub(value1, value2) } } } } const adaptedCalc = mew CalcAdapter() console.log(adaptedCalc.operation(10, 55, 'sub'));

2.2 合成的:它将对象组合起来,以便于将它们作为单个兑现进行操作。

示例:

js
代码解读
复制代码
class Employer { constructor(name, role) { this.name = name this.role = role } print() { console.log('name' + this.name) } } class EmployerGroup { constructor(name, composite=[]) { console.log(name) this.name = name this.composites = composie } print() { console.log(this.name) this.composites.forEach(item => { item.print() }) } } let ravi = new Employer('ravi', 'develpoer') let bhavy = new Employer('bhavy', 'develpoer') let groupDeveopers = new EmployerGroup('Developer', [ravi, bhavy])

2.3 装饰器:动态的添加或覆盖对象的行为

js
代码解读
复制代码
class Shape { constructor(color) { this.color = color } } class Circle extends Shape { constructor(radius = 0) { super() this.radius = radius } resize(factor) { this.radius = factor } toString() { return `圆的半径${radius}` } } class ColoredShape extends Shape { constructor(shape, color) { super() this.shape = shape this.color = color } toString() { return `${this.shape.toString()}颜色${this.color}` } } let circle = new Circle(2) let redCircle = new ColorShape(circle, 'red') redCircle.toString()

2.4 代理:一个类可以表示另外一个类的功能

js
代码解读
复制代码
class Percentage { constructor(percent) { this.percent = percent } toString() { return `${this.percent}` } valueOf() { return this.percent / 100 } } let fivePercent = new Percentage(5) fivePercent.toString() console.log(50 * fivePentent)

3.行为设计模式

行为设计模式特点就是关注对象之间的通信。

3.1 迭代器:访问对象的元素而不暴露其底层表示。

示例:以数组为例

js
代码解读
复制代码
class Stuff { constructor() { this.a = 11 this.b = 22 } [Symbol.iterator]() { let i = 0' let self = this return ( next: function() { return { done: i > 1, value: self[t++ === 0 ? 'a' : 'b'] } } ) } get backwards() { let i = 0; let self = this return ( next: function() { return { done: i > 1, value: self[t++ === 0 ? 'b' : 'a'] } }, [Symbol.iterator]: function() {return this} ) } }

如何使用

js
代码解读
复制代码
let values = [100, 200, 300] for (let i in values) { console.log(i, values[i]) } let stuff = new Stuff() for (let item of stuff) console.log(item) for (let item of stuff.backwards) console.log(item)

3.2 调解员:第三方对象控制两个对象之间的交互

js
代码解读
复制代码
class Person { consructor(name) { this.name = name this.chatLog = [] } receive(sender, message) { let s = `${sender}: ${message}` console.log(`[${this.name}发送信息${s}]`) this.chatLog.push(s) } say(message) { this.room.broadcast(this.name, message) } pm(who, message) { this.room.message(this.name, who, message) } }

创建聊天室

js
代码解读
复制代码
class ChatRoom { constructor() { this.people = [] } broadcast(source, message) { for (let p of this.people) { if (p.name !== source) { p.receive(source, message) } } } join(p) { let joinMsg = `${p.name} 加入聊天室` this.broadcast('room', joinMsg) p.room = this this.people.join(p) } message(source, destination, messge) { for (let p of this.people) { if(p.name == destination) p.receive(source, message) } } }

使用

js
代码解读
复制代码
let room = new ChatRoom() let person1 = new Person('张三') let person2 = new Person('李四') room.join(person1) room.join(person2) person1.say('hello') let person3 = new Person('王五') room.join(person3) person.say('我叫王五')

3.3 观察者:允许多个观察者对象控制一个事件。

js
代码解读
复制代码
class Event { constructor() { this.handlers = new Map() this.count = 0 } subscribe(handler) { this.handler.set(++this.count, handler) return this.count } unsubscribe(idx) { this.handlers.delete(idx) } fire(sender, args) { this.handler.forEach((v, k) => {v(sender, args)}) } } class FallsIllArgs { constructor(address) { this.address = address this.fallsIll = new Event() } catchCold() { this.fallsIll.fire(this, new FallsIllArgs(this.address)) } }

使用

js
代码解读
复制代码
let person new Person('ABC road') let sub = person.fallsIll.subscribe((s, a) => { console.log(`医生被呼叫到${a.address}}`) }) person.catchCold() person.catchCold() person.fallsIll.unsubscribe(sub) person.catchCold()

结语:我们在遇到某些场景时,虽然可以凭借其他方案解决问题,但是也可以尝试使用设计模式的思路去实现,这样不仅可以提升代码的可读性,同时也开阔了自己的思维,不会局限于一种解决方案。虽然使用了设计模式看起来代码量提升了,还会觉得写那么多,都是重复的,确实,但是也不妨碍它能解决一些复杂的问题。

ps: 其中某些本人用过,某些是参考,如有雷同,纯属巧合。

注:本文转载自juejin.cn的前端_ID林的文章"https://juejin.cn/post/7487765743859105826"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

143
阅读
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top