JavaScript
设计模式是编程世界的智慧结晶,提供了解决常见问题的优秀方案。无论你是初学者还是经验丰富的开发者,掌握这些模式都能让你的代码更清晰、更灵活。本文将为你介绍一些常见的设计模式,帮助你提高代码质量,构建更可维护的应用。让我们一起深入了解这些设计模式的精妙之处吧!
设计模式是在软件设计中反复出现的问题的解决方案。它们是经过验证的、可重用的代码设计经验,能够解决特定类型的问题。这些模式帮助开发者更有效地组织和设计代码,提高可维护性和可扩展性。
设计模式可以分为以下几种:
创建模式侧重于对象创建机制,提供以灵活和可控的方式实例化对象的方法。JavaScript 中一些常用的创建型模式如下:
单例模式是一种常见的设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点。单例模式的目的是限制某个类的实例化次数,确保在整个应用中只存在一个实例(如vuex和redux中的store)。
var Singleton = (function () {
var instance; // 存储单例实例
function init() {
// 私有变量和方法
var privateVariable = 'I am private';
function privateMethod() {
console.log('This is a private method');
}
return {
// 公共变量和方法
publicVariable: 'I am public',
publicMethod: function () {
console.log('This is a public method');
},
getPrivateVariable: function () {
return privateVariable;
},
};
}
return {
// 获取单例实例的方法
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
},
};
})();
// 获取单例实例
var mySingleton = Singleton.getInstance();
class Singleton {
static instance; // 静态属性,存储单例实例
constructor() {}
// 静态方法,获取单例实例的方法
static getInstance() {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
}
// 获取单例实例
var mySingleton1 = Singleton.getInstance();
var mySingleton2 = Singleton.getInstance();
console.info(mySingleton1 === mySingleton2); // true
工厂模式是一种创建对象的设计模式,它提供了一种封装对象创建过程的方式,使得代码无需关心具体的实例化过程。工厂模式有助于封装对象的创建过程,提高代码的灵活性和可维护性。在实际应用中,工厂模式经常用于处理对象的创建和组装逻辑。
class Car {
constructor(type, model) {
this.type = type;
this.model = model;
}
}
class CarFactory {
createCar(type, model) {
return new Car(type, model);
}
}
const factory = new CarFactory();
const myCar = factory.createCar('SUV', 'Model 1');
在 JavaScript 中,构造函数模式是一种创建对象的方式,它使用构造函数来实例化对象,并通过 new 关键字来调用构造函数。构造函数模式允许创建具有相似属性和方法的多个对象。
// 构造函数
function Animal(name, species) {
this.name = name;
this.species = species;
this.eat = function () {
console.info('eating');
};
}
const cat = new Animal('Tom', 'Cat');
const dog = new Animal('Pluto', 'Dog');
原型模式是一种创建对象的设计模式,它通过使用原型对象作为对象的模板,允许通过原型链共享属性和方法。在 JavaScript 中,每个对象都有一个指向其原型的链接,通过这个链接,对象可以继承原型的属性和方法。原型模式的优势在于可以实现属性和方法的共享,节省内存,并且可以在运行时动态地添加或修改原型上的属性和方法。这使得原型模式成为 JavaScript 中实现继承的基础。
function Animal(name, species) {
this.name = name;
this.species = species;
}
Animal.prototype.eat = function () {
console.info('eating');
};
const cat = new Animal('Tom', 'Cat');
const dog = new Animal('Pluto', 'Dog');
模块模式是一种用于封装和组织 JavaScript 代码的设计模式,它通过使用闭包来创建私有作用域,从而实现信息隐藏和模块化。模块模式有助于将代码组织成可维护和可重用的单元。模块模式的优势在于提供了一种将代码组织成模块的方式,避免了全局命名空间的污染,并且允许实现信息隐藏。这种模式在现代 JavaScript 开发中常用于构建可维护和模块化的代码。
var MyModule = (function () {
// 私有变量
var privateVariable = 'I am private';
// 私有方法
function privateMethod() {
console.log('This is a private method');
}
// 公共变量和方法
return {
publicVariable: 'I am public',
publicMethod: function () {
console.log('This is a public method');
},
getPrivateVariable: function () {
return privateVariable;
},
};
})();
Builder 模式是一种创建型设计模式,它用于构建复杂对象,将构建过程与表示分离,以便相同的构建过程可以创建不同的表示。在 JavaScript 中,Builder 模式通常通过对象字面量和链式调用来实现。通过使用 Builder 模式,我们可以更灵活地构建对象,支持可选的构建步骤,并避免构造函数参数过于庞大和难以维护的问题。Builder 模式通常在需要创建复杂对象时非常有用。
class ComputerBuilder {
constructor() {
this.computer = {};
}
addCPU(cpu) {
this.computer.cpu = cpu;
return this; // 返回构建器实例,以支持链式调用
}
addRAM(ram) {
this.computer.ram = ram;
return this;
}
addStorage(storage) {
this.computer.storage = storage;
return this;
}
build() {
return this.computer;
}
}
// 使用构建器创建电脑对象
const myComputer = new ComputerBuilder()
.addCPU('Intel i7')
.addRAM('16GB')
.addStorage('512GB SSD')
.build();
结构模式侧重于组织和组合对象以形成更大的结构。它们促进了对象的组合,定义了它们之间的关系,并提供了灵活的方法来操纵它们的结构。JavaScript 中一些常用的结构型模式如下:
装饰器模式是一种结构型设计模式,它允许通过将对象包装在装饰器类的实例中来动态地扩展对象的行为。在 JavaScript 中,装饰器模式通常通过使用函数或类来实现。装饰器模式的优势在于它支持在运行时动态地添加或修改对象的行为,而且可以组合多个装饰器来实现不同的组合效果。这使得代码更具灵活性和可维护性。
class Car {
drive() { console.log('Driving the car'); }
}
// 装饰器类 - 加速装置
class TurboDecorator {
constructor(car) {
this.car = car;
}
drive() {
this.car.drive();
console.log('Turbo boost activated!');
}
}
// 装饰器类 - 音响系统
class StereoDecorator {
constructor(car) {
this.car = car;
}
drive() {
this.car.drive();
console.log('Enjoying music with the stereo system');
}
}
// 创建基础汽车对象
const basicCar = new Car();
// 使用装饰器扩展功能
const turboCar = new TurboDecorator(basicCar);
const luxuryCar = new StereoDecorator(turboCar);
// 调用装饰后的汽车对象的方法
luxuryCar.drive();
Facade 模式是一种结构型设计模式,它提供了一个简化接口,用于访问一个或多个复杂子系统。Facade 模式通过隐藏系统的复杂性,提供了一个更简单和一致的接口,使客户端更容易使用。Facade 模式的目标是简化接口,隐藏复杂性,并提供一个更方便的入口点。这有助于降低系统之间的耦合度,并提高代码的可维护性。
// 子系统 - 播放器
class Player {
play() { console.log('Playing music'); }
stop() { console.log('Stopping music') ; }
}
// 子系统 - 音响
class Stereo {
turnOn() { console.log('Turning on the stereo'); }
turnOff() { console.log('Turning off the stereo'); }
}
// Facade 类 - 音响系统外观
class AudioSystemFacade {
constructor() {
this.player = new Player();
this.stereo = new Stereo();
}
playMusic() {
this.stereo.turnOn();
this.player.play();
}
stopMusic() {
this.player.stop();
this.stereo.turnOff();
}
}
// 使用 Facade 模式简化接口
const audioFacade = new AudioSystemFacade();
audioFacade.playMusic(); // Turning on the stereo, Playing music
audioFacade.stopMusic(); // Stopping music, Turning off the stereo˝
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的对象之间进行合作。适配器模式通过创建一个包装对象(适配器),使原本不兼容的接口变得兼容。通过适配器模式,我们可以在不修改旧的计算器对象的情况下,使其适用于新系统。适配器模式有助于解决接口不兼容的问题,并促使不同系统之间更容易协同工作。
// 旧的计算器对象
class OldCalculator {
getTotal() {
return 100;
}
}
// 新的系统期望的接口
class NewCalculator {
calculate() {
return 200;
}
}
// 适配器类
class CalculatorAdapter {
constructor(oldCalculator) {
this.oldCalculator = oldCalculator;
}
// 适配方法
calculate() {
return this.oldCalculator.getTotal();
}
}
// 使用适配器连接新旧系统
const oldCalculator = new OldCalculator();
const adapter = new CalculatorAdapter(oldCalculator);
console.log('Total using adapter:', adapter.calculate()); // Total using adapter: 100
桥接模式(Bridge Pattern)是一种结构型设计模式,它将一个抽象部分与其具体实现部分分离,使它们可以独立变化。这种模式通过使用组合而不是继承,来将抽象和实现解耦。通过桥接模式,我们可以独立地变化形状和颜色,而不必修改彼此之间的继承关系。这有助于更好地适应变化和提高系统的灵活性。
// 颜色实现类
class RedColor {
applyColor() {
console.log('Applying red color');
}
}
class BlueColor {
applyColor() {
console.log('Applying blue color');
}
}
// 形状抽象类
class Shape {
constructor(color) {
this.color = color;
}
applyColor() {
// 委托给颜色实现类
this.color.applyColor();
}
draw() {
// 具体形状的绘制逻辑
}
}
// 具体形状类
class Circle extends Shape {
draw() {
console.log('Drawing circle');
}
}
class Square extends Shape {
draw() {
console.log('Drawing square');
}
}
// 使用桥接模式连接形状和颜色
const redCircle = new Circle(new RedColor());
const blueSquare = new Square(new BlueColor());
// 调用具体形状的方法,委托给颜色实现类
redCircle.draw(); // Drawing circle
redCircle.applyColor(); // Applying red color
blueSquare.draw(); // Drawing square
blueSquare.applyColor(); // Applying blue color
组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得客户端可以统一对待单个对象和组合对象,从而简化了客户端代码。通过组合模式,我们可以统一对待单个图形和复合图形,使得客户端代码更简单和灵活。这种模式特别适用于处理树状结构的情况。
// 抽象图形类
class Graphic {
draw() {
// 抽象方法,由具体子类实现
}
}
// 具体图形类 - 圆形
class Circle extends Graphic {
constructor(name) {
super();
this.name = name;
}
draw() {
console.log(`Drawing Circle: ${this.name}`);
}
}
// 具体图形类 - 矩形
class Rectangle extends Graphic {
constructor(name) {
super();
this.name = name;
}
draw() {
console.log(`Drawing Rectangle: ${this.name}`);
}
}
// 复合图形类
class CompositeGraphic extends Graphic {
constructor(name) {
super();
this.name = name;
this.graphics = [];
}
add(graphic) {
this.graphics.push(graphic);
}
draw() {
console.log(`Drawing Composite: ${this.name}`);
this.graphics.forEach((graphic) => {
graphic.draw();
});
}
}
// 使用组合模式创建图形结构
const circle1 = new Circle('Circle 1');
const circle2 = new Circle('Circle 2');
const rectangle1 = new Rectangle('Rectangle 1');
const composite = new CompositeGraphic('Composite 1');
composite.add(circle1);
composite.add(rectangle1);
const rootComposite = new CompositeGraphic('Root Composite');
rootComposite.add(composite);
rootComposite.add(circle2);
// 绘制整个图形结构
rootComposite.draw();
行为模式侧重于对象之间的交互和责任的分配。它们为对象之间的通信、协调和协作提供解决方案。JavaScript 中一些常用的行为型模式如下:
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。在 JavaScript 中,观察者模式通常使用回调函数(callbacks)或事件机制来实现。通过观察者模式,我们可以实现对象之间的松耦合,主题和观察者之间的关系更为灵活。当主题的状态发生改变时,所有注册的观察者都会得到通知,可以进行相应的更新操作。这在实现事件处理、数据绑定等场景中非常常见。
// 主题类,负责维护观察者列表,并提供添加、移除和通知观察者的方法
class Subject {
constructor() {
this.observers = [];
}
// 添加观察者
addObserver(observer) {
this.observers.push(observer);
}
// 移除观察者
removeObserver(observer) {
this.observers = this.observers.filter((o) => o !== observer);
}
// 通知所有观察者
notify() {
this.observers.forEach((observer) => {
observer.update();
});
}
}
// 观察者类,具有一个 update 方法,用于在收到通知时执行相应的操作。
class Observer {
constructor(name) {
this.name = name;
}
// 更新方法
update() {
console.log(`${this.name} has been notified and updated.`);
}
}
// 创建主题和观察者
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
// 添加观察者到主题
subject.addObserver(observer1);
subject.addObserver(observer2);
// 通知所有观察者
subject.notify();
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以互相替换。策略模式使得算法的变化独立于使用算法的客户端。通过策略模式,客户端可以在运行时选择不同的支付策略,而不必修改客户端代码。这种模式使得算法的变化独立于客户端,提高了代码的可维护性和灵活性。
// 支付策略接口
class PaymentStrategy {
pay(amount) {
// 策略接口,具体策略类需要实现该方法
}
}
// 具体支付策略 - 支付宝
class AlipayStrategy extends PaymentStrategy {
pay(amount) {
console.log(`Paid ${amount} using Alipay.`);
}
}
// 具体支付策略 - 微信支付
class WeChatPayStrategy extends PaymentStrategy {
pay(amount) {
console.log(`Paid ${amount} using WeChat Pay.`);
}
}
// 具体支付策略 - 信用卡支付
class CreditCardStrategy extends PaymentStrategy {
pay(amount) {
console.log(`Paid ${amount} using Credit Card.`);
}
}
// 上下文类,负责接收并执行具体的支付策略
class PaymentContext {
constructor(strategy) {
this.strategy = strategy;
}
// 设置支付策略
setPaymentStrategy(strategy) {
this.strategy = strategy;
}
// 执行支付策略
executePayment(amount) {
this.strategy.pay(amount);
}
}
// 使用策略模式
const paymentContext = new PaymentContext(new AlipayStrategy());
paymentContext.executePayment(1000); // Paid 1000 using Alipay
// 切换支付策略
paymentContext.setPaymentStrategy(new WeChatPayStrategy());
paymentContext.executePayment(800); // Paid 800 using WeChat Pay
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而允许用不同的请求参数化客户端队列,请求可进行排队、请求可被取消、以及支持可撤销的操作。在 JavaScript 中,命令模式通常通过函数或对象来实现。通过命令模式,我们可以将请求封装成对象,使得可以动态地选择和执行不同的命令。这有助于将请求的发送者和接收者解耦,支持命令的撤销和重做,以及实现一些其他的命令相关的功能。
// 命令接口
class Command {
execute() {
// 命令接口,具体命令类需要实现该方法
}
}
// 具体命令类 - 打开电视
class TurnOnTVCommand extends Command {
constructor(tv) {
super();
this.tv = tv;
}
execute() {
this.tv.turnOn();
}
}
// 具体命令类 - 关闭电视
class TurnOffTVCommand extends Command {
constructor(tv) {
super();
this.tv = tv;
}
execute() {
this.tv.turnOff();
}
}
// 接收者类 - 电视
class TV {
turnOn() {
console.log('TV is turned on.');
}
turnOff() {
console.log('TV is turned off.');
}
}
// 调用者类 - 遥控器
class RemoteControl {
constructor() {
this.command = null;
}
setCommand(command) {
this.command = command;
}
pressButton() {
this.command.execute();
}
}
// 使用命令模式
const tv = new TV();
const turnOnCommand = new TurnOnTVCommand(tv);
const turnOffCommand = new TurnOffTVCommand(tv);
const remoteControl = new RemoteControl();
// 配置遥控器按钮
remoteControl.setCommand(turnOnCommand);
remoteControl.pressButton(); // TV is turned on.
remoteControl.setCommand(turnOffCommand);
remoteControl.pressButton(); // TV is turned off.
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露该对象的内部表示。在 JavaScript 中,迭代器模式通常通过迭代器对象或内置的迭代器接口来实现。
// 自定义迭代器对象
class ArrayIterator {
constructor(array) {
this.array = array;
this.index = 0;
}
hasNext() {
return this.index < this.array.length;
}
next() {
return this.hasNext() ? this.array[this.index++] : null;
}
}
// 使用迭代器模式遍历数组
const array = [1, 2, 3, 4, 5];
const iterator = new ArrayIterator(array);
while (iterator.hasNext()) {
console.log(iterator.next());
}
中介者模式(Mediator Pattern)是一种行为型设计模式,它定义了一个对象,该对象封装了一组对象之间的交互方式。中介者使对象之间不直接相互通信,而是通过中介者对象进行通信,从而降低了对象之间的耦合度。中介者模式适用于需要将多个对象解耦并通过一个中心点进行通信的场景。这可以减少对象之间的直接关联,提高系统的可维护性。
// 聊天室类
class ChatMediator {
constructor() {
this.users = [];
}
addUser(user) {
this.users.push(user);
}
sendMessage(message, sender) {
this.users.forEach((user) => {
if (user !== sender) {
user.receiveMessage(message);
}
});
}
}
// 用户类
class User {
constructor(name, mediator) {
this.name = name;
this.mediator = mediator;
}
sendMessage(message) {
console.log(`${this.name} sending message: ${message}`);
this.mediator.sendMessage(message, this);
}
receiveMessage(message) {
console.log(`${this.name} received message: ${message}`);
}
}
// 使用中介者模式
const mediator = new ChatMediator();
const user1 = new User('User 1', mediator);
const user2 = new User('User 2', mediator);
const user3 = new User('User 3', mediator);
mediator.addUser(user1);
mediator.addUser(user2);
mediator.addUser(user3);
user1.sendMessage('Hello, everyone!'); // User 1 sending message: Hello, everyone!
// User 2 received message: Hello, everyone!
// User 3 received message: Hello, everyone!
user3.sendMessage('Hi there!'); // User 3 sending message: Hi there!
// User 1 received message: Hi there!
// User 2 received message: Hi there!
在JavaScript开发中,设计模式是一种强大的工具,可以帮助我们更好地组织和结构化代码,提高代码的可维护性和可扩展性。本文介绍了一些常见的JavaScript设计模式,包括单例模式、工厂模式、观察者模式、策略模式等。设计模式并不是一成不变的规则,而是在特定情境下的最佳实践。在实际项目中,根据需求和情境选择合适的设计模式是至关重要的。理解和掌握设计模式的原理,有助于我们更好地设计和组织代码结构,提高代码的质量。总之,设计模式是JavaScript开发中的重要主题,通过学习和应用设计模式,我们能够写出更清晰、可维护且更具扩展性的代码。希望本文对你理解和应用JavaScript设计模式提供了一些有用的信息。在实践中不断积累经验,发现适合自己团队和项目的最佳实践。
本文由微信公众号奇舞精选原创,哈喽比特收录。
文章来源:https://mp.weixin.qq.com/s/thyzF3xk0u-utA7mpH5rZQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。