《JavaScript设计模式》——9.10 Factory(工厂)模式

简介:

本节书摘来自异步社区《JavaScript设计模式》一书中的第9章,第9.10节, 作者: 【美】Addy Osmani 译者: 徐涛 更多章节内容可以访问云栖社区“异步社区”公众号查看。

9.10 Factory(工厂)模式

Factory模式是另一种创建型模式,涉及创建对象的概念。其分类不同于其他模式的地方在于它不显式地要求使用一个构造函数。而Factory可以提供一个通用的接口来创建对象,我们可以指定我们所希望创建的工厂对象的类型(见图9-9)。
screenshot

假设有一个UI工厂,我们要创建一个UI组件的类型。不需要直接使用new运算符或者通过另一个创建型构造函数创建这个组件,而是要求Factory对象创建一个新的组件。我们通知Factory需要什么类型的对象(如“按钮”、“面板”),它会进行实例化,然后将它返回给我们使用。

如果对象创建过程相对比较复杂,这种方法特别有用,例如,如果它强烈依赖于动态因素或应用程序配置的话。

可以在ExtJS等UI库中找到此模式的示例,其中创建对象或组件的方法也有可能被归入子类了。

下面这个示例构建在之前的代码片段之上,使用Constructor模式逻辑来定义汽车。它展示了如何使用Factory模式来实现vehicle工厂:

// Types.js –本例构造函数的存放文件
// 定义Car构造函数

function Car(options) {
  // 默认值
  this.doors = options.doors || 4;
  this.state = options.state || "brand new";
  this.color = options.color || "silver";
}

// 定义Truck构造函数

function Truck(options) {
   this.state = options.state || "used";
   this.wheelSize = options.wheelSize || "large";
   this.color = options.color || "blue";
}

// FactoryExample.js
// 定义vehicle工厂的大体代码

function VehicleFactory() { }

// 定义该工厂factory的原型和试用工具,默认的vehicleClass是Car

VehicleFactory.prototype.vehicleClass = Car;

// 创建新Vehicle实例的工厂方法

VehicleFactory.prototype.createVehicle = function (options) {
   if (options.vehicleType === "car") {
       this.vehicleClass = Car;
   } else {
       this.vehicleClass = Truck;
   }
   return new this.vehicleClass(options);
};

// 创建生成汽车的工厂实例

var carFactory = new VehicleFactory();
var car = carFactory.createVehicle({
               vehicleType: "car",
               color: "yellow",
               doors: 6});

// 测试汽车是由vehicleClass的原型prototype里的Car创建的
// 输出: true

console.log(car instanceof Car);

// 输出: Car对象,color: "yellow", doors: 6,state:"brand new"

console.log(car);

在方法 1 中,我们修改了VehicleFactory实例来使用Truck类:

var movingTruck = carFactory.createVehicle({
                      vehicleType: "truck",
                      state: "like new",
                      color: "red",
                      wheelSize: "small"});

// 测试卡车是由vehicleClass的原型prototype里的Truck创建的
// 输出: true

console.log(movingTruck instanceof Truck);

// 输出: Truck对象,color :"red", state:"like new" ,wheelSize:"small"

console.log(movingTruck);

在方法2中,我们把VehicleFactory归入子类来创建一个构建Truck的工厂类:

function TruckFactory() { }
TruckFactory.prototype = new VehicleFactory();
TruckFactory.prototype.vehicleClass = Truck;
var truckFactory = new TruckFactory();
var myBigTruck = truckFactory.createVehicle({
                      state: "omg..so bad.",
                      color: "pink",
                      wheelSize: "so big"});

// 确认myBigTruck是由原型Truck创建的
// 输出: true

console.log(myBigTruck instanceof Truck);

// 输出:Truck对象,color: pink", wheelSize: "so big", state: "omg. so bad"

console.log(myBigTruck);

9.10.1 何时使用Factory模式
Factory模式应用于如下场景时是特别有用的:

当对象或组件设置涉及高复杂性时
当需要根据所在的不同环境轻松生成对象的不同实例时
当处理很多共享相同属性的小型对象或组件时
在编写只需要满足一个API契约(亦称鸭子类型)的其他对象的实例对象时。对于解耦是很有用的。
9.10.2 何时不应使用Factory模式
如果应用错误,这种模式会为应用程序带来大量不必要的复杂性。除非为创建对象提供一个接口是我们正在编写的库或框架的设计目标,否则我建议坚持使用显式构造函数,以避免不必要的开销。

由于对象创建的过程实际上是藏身接口之后抽象出来的,单元测试也可能带来问题,这取决于对象创建的过程有多复杂。

9.10.3 Abstract Factory(抽象工厂)
了解抽象工厂模式也是有用的,它用于封装一组具有共同目标的单个工厂。它能够将一组对象的实现细节从一般用法中分离出来。

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

既简单又容易理解的示例是车辆工厂,它定义了获取或注册车辆类型的方法。抽象工厂可以命名为AbstractVehicleFactory。抽象工厂将允许对像car或truck这样的车辆类型进行定义,具体工厂只需要实现履行车辆契约的类(如Vehicle.prototype.drive和Vehicle.prototype.breakDown)。

var AbstractVehicleFactory = (function () {
// 存储车辆类型
  var types = {};
  return {
       getVehicle: function ( type, customizations ) {
            var Vehicle = types[type];
            return (Vehicle) ? return new Vehicle(customizations) : null;
       },
       registerVehicle: function ( type, Vehicle ) {
            var proto = Vehicle.prototype;
            // 只注册实现车辆契约的类
            if ( proto.drive && proto.breakDown ) {
                  types[type] = Vehicle;
            }
            return AbstractVehicleFactory;
        }
  };
})();
// 用法:
AbstractVehicleFactory.registerVehicle( "car", Car );
AbstractVehicleFactory.registerVehicle( "truck", Truck );
// 基于抽象车辆类型实例化一个新car对象
var car = AbstractVehicleFactory.getVehicle( "car" , {
             color: "lime green",
             state: "like new" } );
// 同理实例化一个新truck对象
var truck = AbstractVehicleFactory.getVehicle( "truck" , {
                wheelSize: "medium",
                color: "neon yellow" } );
相关文章
|
11月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
315 16
|
11月前
|
设计模式 Java 关系型数据库
【设计模式】【创建型模式】抽象工厂模式(Abstract Factory)
一、入门 什么是抽象工厂模式? 抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建相关或依赖对象的家族,而不需要指定具体的类。 简单来说,抽象工厂模式是工厂方法模式的升级版,它能够创建一组相
370 14
|
11月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
317 0
|
11月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
432 0
|
11月前
|
设计模式 安全 Java
并发设计模式实战系列(12):不变模式(Immutable Object)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十二章,废话不多说直接开始~
267 0
|
11月前
|
设计模式 算法 Java
设计模式觉醒系列(04)策略模式|简单工厂模式的升级版
本文介绍了简单工厂模式与策略模式的概念及其融合实践。简单工厂模式用于对象创建,通过隐藏实现细节简化代码;策略模式关注行为封装与切换,支持动态替换算法,增强灵活性。两者结合形成“策略工厂”,既简化对象创建又保持低耦合。文章通过支付案例演示了模式的应用,并强调实际开发中应根据需求选择合适的设计模式,避免生搬硬套。最后推荐了JVM调优、并发编程等技术专题,助力开发者提升技能。
|
11月前
|
设计模式 Prometheus 监控
并发设计模式实战系列(20):扇出/扇入模式(Fan-Out/Fan-In)(完结篇)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第二十章,废话不多说直接开始~
356 0
|
设计模式 Java 关系型数据库
设计模式:工厂方法模式(Factory Method)
工厂方法模式是一种创建型设计模式,通过将对象的创建延迟到子类实现解耦。其核心是抽象工厂声明工厂方法返回抽象产品,具体工厂重写该方法返回具体产品实例。适用于动态扩展产品类型、复杂创建逻辑和框架设计等场景,如日志记录器、数据库连接池等。优点包括符合开闭原则、解耦客户端与具体产品;缺点是可能增加类数量和复杂度。典型应用如Java集合框架、Spring BeanFactory等。
|
设计模式 Java
课时89:工厂设计模式
课时89介绍工厂设计模式(Factory),涵盖接口的定义与使用、程序结构设计及工厂设计的核心概念。通过实例代码展示如何利用接口实现子类的向上转型,并通过工厂类解耦主类与子类的关系,从而实现更灵活和可扩展的设计。工厂模式使客户端无需关心具体子类的创建过程,仅需通过工厂类获取对象实例,简化了系统的维护和扩展。
188 1
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
254 2