设计模式(四):单例模式与工厂模式

简介:

在未读《JavaScript设计模式》这本书前,在我的印象里,单例模式就是每个类只会产生一个实例,非常简单。在细看到这个模式时候,有些疑惑单例模式与工厂模式的区别,虽然看起来像最大区别在于是否多次实例化。

单例(Singleton)模式

单例模式它限制了类的实例化次数只能一次。在实例不存在的情况下,可以通过一个方法创建一个类来实现创建类的新实例;如果实例已经存在,它会简单返回该对象的引用。(这跟我想的一样)

例子:

复制代码
var mySingleton = (function () {
  // Instance stores a reference to the Singleton
  var instance;
  function init() {
    // Singleton
    // Private methods and variables
    function privateMethod(){
        console.log( "I am private" );
    }
    var privateVariable = "Im also private";
    var privateRandomNumber = Math.random();
    return {
      // Public methods and variables
      publicMethod: function () {
        console.log( "The public can see me!" );
      },
      publicProperty: "I am also public",
      getRandomNumber: function() {
        return privateRandomNumber;
      }
    };
  };
  return {
    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: function () {
      if ( !instance ) {
        instance = init();
      }
      return instance;
    }
  };
})();
复制代码

特别地方:

1. 单例不同于静态类(或对象),因为我们可以推迟它们的初始化(通常是因为它们需要的参数信息在类定义时是无法获得的),直到需要使用静态实例时,无需使用资源或内存。

2. 单例的唯一实例能够通过子类去扩展,使用者不用更改代码就能使用一个扩展的实例。

3. 单例将导致测试变困难,不利于单元测试。

何时使用单例(When it really is a singleton):

一个类是否是一个单例,必须确定下面三点:

1. Will every application use this class exactly the same way? (exactly is the key word)

2. Will every application ever need only one instance of this class? (ever and one are the key words)

3. Should the clients of this class be unaware of the application they are part of?

PS:这三点是由文章http://www.ibm.com/developerworks/webservices/library/co-single/index.html提出。

我的理解是:

1. 是否每个应用程序使用这个类的方式都完全相同?

2. 是否每个应用程序任何时候都只需要一个类的实例?

3. 使用者不需要知道该类是这应用程序的哪个部分?(或许翻译不好)

当满足这三个点,那就可以用单例。关键就在于类的使用方式都相同,并且不需要应用上下文。

工厂(Factory)模式

工厂模式提供一个通用的接口来创建对象。

例子:

复制代码
function Car( options ) {
  this.doors = options.doors || 4;
  this.state = options.state || "brand new";
  this.color = options.color || "silver";
}
 
function Truck( options){
  this.state = options.state || "used";
  this.wheelSize = options.wheelSize || "large";
  this.color = options.color || "blue";
}
 
function VehicleFactory() {}
VehicleFactory.prototype.createVehicle = function ( options ) {
  switch(options.vehicleType){
    case "car":
      this.vehicleClass = Car;
      break;
    case "truck":
      this.vehicleClass = Truck;
      break;
    //defaults to VehicleFactory.prototype.vehicleClass (Car)
  }
  return new this.vehicleClass( options );
};
var carFactory = new VehicleFactory();
var car = carFactory.createVehicle( {
            vehicleType: "car",
            color: "yellow",
            doors: 6 } );
console.log( car instanceof Car ); // Outputs: true
复制代码

何时使用工厂:

1. 当对象或组件设置非常复杂的时候。

2. 当需要根据所在的不同环境轻松生成对象的不同实例时。

3. 当处理很多共享相同属性的小型对象或组件时。

4. 对象的实例只需要满足一个约定——鸭子类型(duck typing)。利于解耦。

PS:鸭子类型——“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

抽象工厂(Abstract Factory)模式

书中描述:

使用抽象工厂模式场景:一个系统必须独立于它所创建的对象的生成方式,或它需要与多种对象类型一起工作。

PS:我觉得没描述清楚。

网上定义:

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

PS:这个才比较清晰。

我的理解:

在工厂模式的加上一层抽象,工厂的工厂。

 

总结

单例模式和工厂模式概念上是比较简单,但是在使用上需要留心。该不该用单例,就考虑上面讲的单例三要点;该不该用工厂,就要看它是否带来大量不必要的复杂性,带来不必要的开销(不为了用模式而用模式)。抽象工厂模式并没有找到好的示例,就先略下。

另外越读这本书,越觉得在某些译文上有些问题,太过于直译,我觉得应该要结合理解做翻译,不然就像外国人讲普通话,太怪了。

 

参考文献

1. 《Learning JavaScript Design Patterns》 by Addy Osmani

https://addyosmani.com/resources/essentialjsdesignpatterns/book/

2. 《JavaScript设计模式》by 徐涛【译】

 

本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。

本文地址 :http://www.cnblogs.com/lovesong/p/5573521.html


本文转自 海角在眼前 博客园博客,原文链接:http://www.cnblogs.com/lovesong/p/5573521.html   ,如需转载请自行联系原作者

相关文章
|
4月前
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
162 15
|
5月前
|
设计模式 存储 安全
设计模式-单例模式练习
单例模式是Java设计模式中的重要概念,确保一个类只有一个实例并提供全局访问点。本文详解单例模式的核心思想、实现方式及线程安全问题,包括基础实现(双重检查锁)、懒汉式与饿汉式对比,以及枚举实现的优势。通过代码示例和类图,深入探讨不同场景下的单例应用,如线程安全、防止反射攻击和序列化破坏等,展示枚举实现的简洁与可靠性。
106 0
|
6月前
|
设计模式 安全 Java
设计模式:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数、自行创建实例和静态方法(如`getInstance()`)实现。适用于数据库连接池、日志管理器等需要全局唯一对象的场景。常见的实现方式包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举。线程安全问题可通过`synchronized`或双重检查锁解决,同时需防止反射和序列化破坏单例。优点是避免资源浪费,缺点是可能增加代码耦合度和测试难度。实际开发中应优先选择枚举或静态内部类,避免滥用单例,并结合依赖注入框架优化使用。
|
7月前
|
设计模式 存储 安全
设计模式2:单例模式
单例模式是一种创建型模式,确保一个类只有一个实例,并提供全局访问点。分为懒汉式和饿汉式: - **懒汉式**:延迟加载,首次调用时创建实例,线程安全通过双重检查锁(double check locking)实现,使用`volatile`防止指令重排序。 - **饿汉式**:类加载时即创建实例,线程安全但可能浪费内存。 示例代码展示了如何使用Java实现这两种模式。
116 4
|
9月前
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
346 13
|
9月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
105 2
|
10月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
138 4
|
10月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
10月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
10月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
74 0