JavaScript设计模式详解

这篇具有很好参考价值的文章主要介绍了JavaScript设计模式详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JavaScript设计模式是解决软件设计中常见问题的可重复使用的解决方案。本博客将深入探讨JavaScript设计模式的各个方面,包括设计模式的类别、创建型、结构型、行为型、并发型和架构型设计模式。

设计模式概述

什么是设计模式?

设计模式是一种在软件设计中解决常见问题的可重用解决方案。它们是经过验证的、通用的设计思想,提供了一种解决软件设计中反复出现问题的方法。设计模式不是可直接转化成代码的具体算法,而是关于如何解决某一类问题的指导性方案。

设计模式的好处包括提高代码的可重用性、可维护性、可扩展性,同时也有助于降低代码的复杂性。

设计模式的分类

设计模式可以分为不同的类别,主要包括:

1. Proto-patterns(原型模式)和 Anti-patterns(反模式):  这些是在设计模式被广泛接受之前的阶段。Proto-patterns 是被开发者社区认可并广泛使用的设计模式,而 Anti-patterns 代表不良实践。

2. 创建型设计模式(Creational Design Patterns):  处理对象的创建机制,优化对象的创建过程。包括工厂方法、抽象工厂、建造者、原型和单例等。

3. 结构型设计模式(Structural Design Patterns):  处理对象之间的关系,确保系统的一部分变化时,整个系统不需要随之改变。包括适配器、桥接、组合、装饰者、外观、享元和代理等。

4. 行为型设计模式(Behavioral Design Patterns):  识别、实施和改进系统中不同对象之间的通信。确保系统的不同部分具有同步的信息。包括责任链、命令、迭代器、中介者、备忘录、观察者、状态、策略和访问者等。

5. 并发型设计模式(Concurrency Design Patterns):  处理多线程编程范例,包括活动对象、核反应和调度程序等。

6. 架构型设计模式(Architectural Design Patterns):  用于架构目的的设计模式,包括MVC(模型-视图-控制器)、MVP(模型-视图-表示器)和MVVM(模型-视图-视图模型)等。

原型模式和反模式

原型模式是什么?

Proto-patterns(原型模式)是指那些在设计模式被广泛接受之前的阶段,由开发者个体提出并在实践中得到验证的设计思想。当一个开发者在解决某一问题时,可能会想到一个独特的解决方案,这个解决方案并没有被广泛认可和文档化,但开发者自身认为它具有可重用性,并认为开发者社区会从中受益。这个阶段被称为 Proto-pattern,意味着这是一个潜在的设计模式,但尚未被完全确认和纳入标准。

如文章中所述,一个 Proto-pattern 在变成一个正式的设计模式之前,需要经历一定的测试阶段,由各种开发者和场景验证,以确保该模式在实践中是有用的、并能够提供正确的结果。通常,将一个 Proto-pattern 转变为完全成熟的模式需要大量的工作和文档化。

如何辨别设计模式?

辨别设计模式的方法通常包括以下几个方面:

1. 问题的复发性:  设计模式是为解决在软件设计中反复出现的问题而提出的,因此首先需要观察问题是否是一种常见的、具有一般性的问题。

2. 通用性:  设计模式通常是一种通用的解决方案,而不是特定于某个特定应用的解决方案。如果一个解决方案在多个上下文中都适用,可能是一个设计模式。

3. 可重用性:  设计模式应该是可重用的,可以在不同的情境中应用。如果解决方案只在特定情境下有用,可能更适合被称为特定应用的最佳实践,而不是设计模式。

4. 文档和社区认可:  成熟的设计模式通常有相应的文档和社区认可。它们被广泛讨论、使用,并有相关的资料可以供开发者学习和参考。

反模式的概念和例子

反模式是指在软件设计和开发中,被认为是不良实践或导致问题的常见做法。这些是反面教材,指导开发者在设计和编码时应该避免的模式。使用 Anti-pattern 可能导致代码不可维护、难以理解、性能低下等问题。

1. 修改 Object 类原型(Modifying Object Class Prototype):  在 JavaScript 中修改 Object 类的原型,影响了所有继承自 Object 的对象,可能导致不可预测的行为和潜在的冲突。

Object.prototype.newMethod = function() {
   // 新增的方法
};

2. 在不拥有的对象上进行修改(Modifying Objects You Don’t Own):  修改第三方库或框架中的对象,可能导致兼容性问题和难以维护的代码。

// 在第三方库的对象上添加新方法
thirdPartyLibrary.someObject.newMethod = function() {
   // 新增的方法
};

3. 过度使用全局变量(Overusing Global Variables):  过度使用全局变量会增加代码的耦合度,降低模块化和可维护性。

 // 过度使用全局变量
 var globalVariable = 'some value';

 function exampleFunction() {
     console.log(globalVariable);
 }

设计模式分类详解

设计模式是在软件设计中为解决特定问题而提出的一套经过验证的通用解决方案。这些模式有助于在设计阶段采用经验丰富的最佳实践,提高代码的可维护性、可扩展性和重用性。下面详细介绍几种常见的设计模式分类及其具体模式。

Creational Design Patterns(创建型设计模式)

这些模式关注对象的创建机制,旨在解决对象的实例化过程中可能引起的问题。

1. Factory Method(工厂方法):  定义一个用于创建对象的接口,由子类决定实例化哪个类。它使一个类的实例化延迟到其子类。

2. Abstract Factory(抽象工厂):  提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定它们的具体类。

3. Builder(建造者):  将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

4. Prototype(原型):  通过复制现有对象来创建新对象,而不是从头开始创建。适用于对象创建的成本较高的情况。

5. Singleton(单例):  确保一个类只有一个实例,并提供全局访问点。

Structural Design Patterns(结构型设计模式)

这些模式关注对象的组合,帮助定义不同对象之间的关系。

1. Adapter(适配器):  将一个接口转换成另一个客户希望的接口,使得原本不兼容的类可以一起工作。

2. Bridge(桥接):  将抽象部分与它的实现部分分离,以便两者可以独立地变化。

3. Composite(组合):  将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端统一对待单个对象和组合对象。

4. Decorator(装饰器):  动态地给一个对象添加一些额外的职责,同时保持原有对象的结构。

5. Facade(外观):  为子系统中的一组接口提供一个一致的界面,使得子系统更容易使用。

6. Flyweight(享元):  通过共享已经存在的相似对象来最小化内存使用或计算开销。

7. Proxy(代理):  为其他对象提供一种代理以控制对这个对象的访问。

Behavioral Design Patterns(行为型设计模式)

这些模式关注对象之间的通信,定义了它们之间的算法和责任。

1. Chain of Responsibility(责任链):  通过传递请求沿链来处理请求,直到有一个对象处理它。

2. Command(命令):  将请求封装成对象,以便使用不同的请求、队列或日志来参数化其他对象。

3. Iterator(迭代器):  提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示。

4. Mediator(中介者):  用一个中介对象来封装一系列的对象交互,使得对象之间松散耦合。

5. Memento(备忘录):  在不暴露对象内部表示的情况下,捕获并且保存对象的内部状态,以后可以恢复到这个状态。

6. Observer(观察者):  定义了对象之间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都得到通知并被自动更新。

7. State(状态):  允许对象在其内部状态改变时改变其行为,对象看起来似乎修改了它的类。

8. Strategy(策略):  定义一系列算法,将它们封装起来,并且使它们可以互相替换。

9. Visitor(访问者):  表示一个作用于某对象结构中的各元素的操作。可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

Concurrency Design Patterns(并发设计模式)

这些模式关注多线程和并发编程中的问题和解决方案。

1. Active Object(主动对象):  将每个请求封装成对象,然后由一个专门的线程调度这些对象。

2. Nuclear Reaction(核反应):  通过将任务划分成可并行执行的小任务,以提高计算效率。

3. Scheduler(调度器):  控制并发执行的任务顺序,使得程序能够以期望的方式运行。

Architectural Design Patterns(架构设计模式)

这些模式关注整个软件架构的组织和结构。

1. MVC(Model-View-Controller):  将应用程序分为三个组件:模型(应用程序数据和业务逻辑)、视图(用户界面元素)和控制器(处理用户输入和管理视图与模型之间的交互)。

2. MVP(Model-View-Presenter):  类似于MVC,但是Presenter处理用户输入并更新视图,同时负责更新模型。

3. MVVM(Model-View-ViewModel):  将视图和模型分离,使用一个中介层(ViewModel)来处理用户输入并更新模型,然后通知视图进行更新。

设计模式示例

以下是每个设计模式的具体示例:

1. Constructor Pattern(构造函数模式):

function Person(name, age) {
    this.name = name;
    this.age = age;
}

// Usage
const person1 = new Person('John', 25);
const person2 = new Person('Jane', 30);

2. Module Pattern(模块模式):

const CounterModule = (function () {
    let count = 0;

    function increment() {
        count++;
    }

    function decrement() {
        count--;
    }

    function getCount() {
        return count;
    }

    return {
        increment,
        decrement,
        getCount
    };
})();

// Usage
CounterModule.increment();
console.log(CounterModule.getCount()); // Output: 1

3. Revealing Module Pattern(揭示模块模式):

const RevealingCounterModule = (function () {
    let count = 0;

    function increment() {
        count++;
    }

    function decrement() {
        count--;
    }

    function getCount() {
        return count;
    }

    return {
        increment,
        decrement,
        getCount
    };
})();

// Usage
RevealingCounterModule.increment();
console.log(RevealingCounterModule.getCount()); // Output: 1

4. Singleton Pattern(单例模式):

const Singleton = (function () {
    let instance;

    function createInstance() {
        // Private method to create a singleton instance
        return { message: 'This is a singleton instance.' };
    }

    return {
        getInstance: function () {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

// Usage
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // Output: true

5. Observer Pattern(观察者模式):

class Observer {
    constructor() {
        this.observers = [];
    }

    subscribe(callback) {
        this.observers.push(callback);
    }

    unsubscribe(callback) {
        this.observers = this.observers.filter(observer => observer !== callback);
    }

    notify(data) {
        this.observers.forEach(observer => observer(data));
    }
}

// Usage
const observer = new Observer();

const callback1 = data => console.log(`Callback 1: ${data}`);
const callback2 = data => console.log(`Callback 2: ${data}`);

observer.subscribe(callback1);
observer.subscribe(callback2);

observer.notify('Data has been updated.'); 
// Output: 
// Callback 1: Data has been updated.
// Callback 2: Data has been updated.

6. Mediator Pattern(中介者模式):

class Mediator {
    constructor() {
        this.colleagues = [];
    }

    addColleague(colleague) {
        this.colleagues.push(colleague);
    }

    mediate(originator, message) {
        this.colleagues.forEach(colleague => {
            if (colleague !== originator) {
                colleague.receive(message);
            }
        });
    }
}

class Colleague {
    constructor(mediator, name) {
        this.mediator = mediator;
        this.name = name;
        this.mediator.addColleague(this);
    }

    send(message) {
        this.mediator.mediate(this, message);
    }

    receive(message) {
        console.log(`${this.name} received: ${message}`);
    }
}

// Usage
const mediator = new Mediator();
const colleague1 = new Colleague(mediator, 'Colleague 1');
const colleague2 = new Colleague(mediator, 'Colleague 2');

colleague1.send('Hello from Colleague 1!');
// Output: Colleague 2 received: Hello from Colleague 1!

7. Prototype Pattern(原型模式):

const Dog = {
    breed: 'Unknown',
    clone: function () {
        const clone = Object.create(this);
        clone.sound = 'Woof';
        return clone;
    }
};

// Usage
const dog1 = Dog.clone();
dog1.breed = 'Labrador';

const dog2 = Dog.clone();
dog2.breed = 'Poodle';

console.log(dog1.sound); // Output: Woof
console.log(dog1.breed); // Output: Labrador

console.log(dog2.sound); // Output: Woof
console.log(dog2.breed); // Output: Poodle

8. Command Pattern(命令模式):

class Command {
    constructor(receiver) {
        this.receiver = receiver;
    }

    execute() {
        throw new Error('execute method must be overridden');
    }
}

class ConcreteCommand extends Command {
    execute() {
        this.receiver.action();
    }
}

class Receiver {
    action() {
        console.log('Receiver is performing an action.');
    }
}

class Invoker {
    constructor(command) {
        this.command = command;
    }

    invoke() {
        this.command.execute();
    }
}

// Usage
const receiver = new Receiver();
const command = new ConcreteCommand(receiver);
const invoker = new Invoker(command);

invoker.invoke(); // Output: Receiver is performing an action.

9. Facade Pattern(外观模式):文章来源地址https://www.toymoban.com/news/detail-803704.html

class Subsystem1 {
    operation() {
        return 'Subsystem 1 operation';
    }
}

class Subsystem2 {
    operation() {
        return 'Subsystem 2 operation';
    }
}

class Facade {
    constructor(subsystem1, subsystem2) {
        this.subsystem1 = subsystem1;
        this.subsystem2 = subsystem2;
    }

    operation() {
        const result1 = this.subsystem1.operation();
        const result2 = this.subsystem2.operation();
        return `${result1}\n${result2}`;
    }
}

// Usage
const subsystem1 = new Subsystem1();
const subsystem2 = new Subsystem2();
const facade = new Facade(subsystem1, subsystem2);

console.log(facade.operation());
// Output:
// Subsystem 1 operation
// Subsystem 2 operation

到了这里,关于JavaScript设计模式详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • javaScript设计模式-工厂

    它的好处是消除对象间的耦合度,在派生子类时提供了更大的灵活性。但盲目的把普通的构造函数扔在一边,并不值得提倡。如果要采一不可能另外换用一个类,或都不需要在运行期间在一系列可互换的类中进行选择,就不应该使用。这样在后期代码重构时还有机会使用。

    2024年01月20日
    浏览(56)
  • javascript设计模式-组合

    组合模式 是一种专为创建WEB上的动态用户界面而量身定制的模式。使用它,可以用一条命令在多个对象上激发复杂或递归行为,那些复杂行为被委托给各个对象。前提是每个对象必须实现相同的接口。接口检查越严格,其稳定性越高。 可以用同样的方法处理对象的集合与其

    2024年01月21日
    浏览(42)
  • javaScript设计模式-单例

    确保一个类只有一个实例,并提供全局访问点。 这个模式有三种不同的实现方式,每种都合理。但各有各的用处,其实用static类也可以实现相似的功能,不同的是单例是使用再创建,static是JVM加载时就创建。 单例提供了将代码组织为一个逻辑单元的手段,它有许多用途:可

    2024年01月19日
    浏览(40)
  • JavaScript 设计模式之享元模式

    将一部分共用的方法提取出来作为公用的模块 享元模式的应用目的是为了提高程序的执行效率与系统的性能。因此在大型系统开发中应用是比较广泛的,有时可以发生质的改变。它可以避免程序中的数据重复。有时系统内存在大量对象,会造成大量存占用,所以应用享元模式

    2024年02月22日
    浏览(42)
  • javascript设计模式-责任链

    责任链 可以用来消除请求的发送者和接收者之间的耦合,这是通过实现一个由隐式地对请求进行处理的对象组成的链而做到的。链中的每个对象可以处理请求,也可以将其传给下一个对象。JS内部就使用了这种模式来处一事件捕获和冒泡问题。一般的结构如下: 发送者知道链

    2024年01月23日
    浏览(44)
  • javascript设计模式-应用示例

    有些时候为了适应没的场景,有些代码没必要每次调用时都进行一次环境判断,所以可以memoizing技术动态改写运行中代码的实现。 发起多个请求,程序会自动缓存,并通过setTimeOut重复调用。 这个例子充分应用了通道方法,利用此模式应该可以做到AOP的功能。

    2024年01月23日
    浏览(42)
  • JavaScript中的设计模式

    本文作者为 360 奇舞团前端开发工程师 JavaScript 设计模式是编程世界的智慧结晶,提供了解决常见问题的优秀方案。无论你是初学者还是经验丰富的开发者,掌握这些模式都能让你的代码更清晰、更灵活。本文将为你介绍一些常见的设计模式,帮助你提高代码质量,构建更可

    2024年02月21日
    浏览(40)
  • javascript设计模式-装饰者

    基本实现 是一种为对象增加我的技术,它并不使用创建新子类手段,一切都在动态完成。这个过程相对于使用者来说是透明的。透明地把对象包装在具有同样接口的另一个对象之中。 比如可以动态的为自行车对象添加可选的特色配件上。比如添加4个选件,可以新定义4个超类

    2024年01月22日
    浏览(48)
  • JavaScript设计模式(五)——发布订阅模式、桥接模式、组合模式

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,正逐渐往全干发展 📃 个人状态: 研发工程师,现效力于中国工业软件事业 🚀 人生格言: 积跬步至千里,积小流成江海 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒

    2024年02月09日
    浏览(48)
  • JavaScript设计模式(一)——构造器模式、原型模式、类模式

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,正逐渐往全干发展 📃 个人状态: 研发工程师,现效力于中国工业软件事业 🚀 人生格言: 积跬步至千里,积小流成江海 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒

    2024年02月11日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包