我是靠谱客的博主 狂野项链,最近开发中收集的这篇文章主要介绍设计一个矩形类rectangle_TypeScript 设计模式与重构技巧 · 工厂模式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

面向对象的核心就是类和对象,在正式进入工厂模式之前,我们不妨先来认识下三大类设计模式。

  • 创建型:简单工厂模式、工厂方法、抽象工厂模式、建造者模式、单例模式
  • 结构型:适配器模式、桥接模式、装饰模式、外观模式、享元模式、代理模式
  • 行为型:命令模式、中介者模式、观察者模式、状态模式、策略模式

而这三大类设计模式也分别针对三类问题:

  • 创建型:如何创建对象
  • 结构型:如何将零散的类和对象组合成为更强大的结构
  • 行为型:类与对象之间的行为分配

一、「创建型」设计模式

建议通过 3W 模型来学习设计模式:

  • What: 是什么?
  • Why:为什么?
  • How:怎么做?

对应起来则是:

1.「创建型」设计模式是什么?

创建型设计模式包含工厂模式、建造者模式、单例模式、原型模式

2.为什么使用「创建型」设计模式

  • 只使用 new 来直接创建对象并不妥,尤其是针对于复杂应用时
  • 同样是创建对象,理应有更”优雅“的创建方式
  • 当创建对象时,「创建型」设计模式就会给予你灵感

3.如何使用「创建型」设计模式

  • 掌握并熟练运用工厂模式
  • 熟悉并熟练运用建造者模式
  • 熟悉并熟练运用单例模式
  • 熟悉并熟练运用原型模式

想要熟练掌握并运用好「创建型」设计模式,离不开对每个设计模式的掌握,那么本篇将会通过一个简化版的图形标注器功能来和大家一起探索 TypeScript 中工厂模式的实践。

二、简单工厂模式

图形标注器是一个比较复杂的组件,一般来说会包含椭圆画笔、矩形画笔和多边形画笔,这三种画笔分别对应三种图形的绘制。

不妨假设这三种画笔分别对应三个类

// 用来继承的抽象画笔父类
abstract class Pencil {
  abstract draw();
}

// 椭圆
class EllipsePencil extends Pencil {
  draw() {
    // ...
  }
}

// 矩形
class RectanglePencil extends Pencil {
  draw() {
    // ...
  }	
}

// 多边形
class PolygonPencil extends Pencil {
  draw() {
    // ...
  }
}

创建对象时,我们依据通过传递参数的形式来创建不同的对象

class SimpleFactory {
  createPencil(type: string) {
    if( type === 'rectangle' ) {
      return new RectanglePencil();
    } else if ( type === 'ellipse' ) {
      return new EllipsePencil();
    } else if ( type === 'polygon' ) {
      return new PolygonPencil();
    }
  }
}

在客户端中调用简单工厂

// 使用了简单工厂的客户端:
const factory = new SimpleFactory();
const pencil = factory.createPencil('rectangle');

如果我们不使用简单工厂模式,而是在客户端中直接调用对应的类,大概长这个样子:

// 未使用简单工厂的客户端:
// 当需要矩形画笔时
const rectanglePencil = new RectanglePencil();
// 当需要椭圆画笔时
const ellipsePencil = new EllipsePencil();
// 当需要多边形画笔时
const polygonPencil = new PolygonPencil();

经过对比,我们不难发现简单工厂的一些特点:

1.简单工厂必须包含必要的判断逻辑

在 SimpleFactory 的 createPencil() 方法中,通过传入不同的类型来返回具体需要创建的对象。

2.客户端无需知道需要创建的具体类,只需要知道传入的参数就可以了

对于客户端来说,根本无需关心具体是由哪个画笔类创建的对象,只需要关心自己传入什么参数可以拿到这些对象就可以了。

3.新增的配置也无需修改客户端的代码

如果需要新增直线画笔 LinePencil 类,根本无需对客户端代码做修改,只需要对简单工厂内部做修改就可以了。

三、工厂方法模式

但是简单工厂模式暴露出一个问题,如果我们不断的新增一些画笔类型,那么每次都要在简单工厂内部新增判断条件。有没有什么方法不需要改变已有代码,而是可以更好的扩展它呢?

我们可以创建多个工厂,每个工厂负责一种对象的创建,而核心的工厂类只用于继承而

abstract class Factory {
  abstract createPencil();
}

class RectangleFactory extends Factory {
  createPencil() {
    return new RectanglePencil();
  }
}

class EllipseFactory extends Factory {
  createPencil() {
    return new EllipsePencil()
  }
}

class PolygonFactory extends Factory {
  createPencil() {
    return new PolygonPencil();
  }
}

在客户端代码中,我们如果想要创建多边形画笔,只需要这样做:

const factory: Factory = PolygonFactory();
const pencil = factory.createPencil();

如果我们想要额外新增一个直线画笔,那么只需要新增对应的工厂和直线画笔类就可以了

class LinePencil extends Pencil {
  draw() {
    // ...
  }
}

class LineFactory extends Factory {
  createPencil() {
    return new LinePencil();
  }
}

在客户端中创建时,修改具体的创建工厂就可以了

const factory: Factory = LineFactory();  // 修改为创建直线画笔的工厂
const pencil = factory.createPencil();

对比简单工厂模式,我们使用多态的方式消除了 if else 这类代码,新增不同的画笔工厂也不需要修改已有的工厂代码,而是直接添加新的工厂就可以了。

四、抽象工厂模式

一个工厂往往不会生产一种产品,一个矩形画笔可能是画矩形框,也有可能画矩形遮罩,这也就意味着父类 Factory 除了包含 createPencil() 方法以外,还会包含 createMask() 方法。

针对创建遮罩功能,我们定义一些新的类

abstract class Mask {
  abstract draw();
}

class RectangleMask extends Mask {
  draw() {
    // ...
  }
}

class EllipseMask extends Mask {
  draw() {
    // ...
  }
}

class PolygonMask extends Mask {
  draw() {
    // ...
  }
}

我们再更新下 Factory 父类

abstract class Factory {
  abstract createPencil();
  abstract createMask();
}

子类也要添加相应的方法

class RectangleFactory extends Factory {
  createPencil() {
    return new RectanglePencil();
  }

  createMask() {
    return new RectangleMask();
  }
}

class EllipseFactory extends Factory {
  createPencil() {
    return new EllipsePencil()
  }

  createMask() {
    return new EllipseMask();
  }
}

class PolygonFactory extends Factory {
  createPencil() {
    return new PolygonPencil();
  }

  createMask() {
    return new PolygonMask();
  }
}

如果客户端中需要创建遮罩,调用对应工厂的方法就可以了

const factory: Factory = new RectangleFactory();
const mask = factory.createMask();  // 创建遮罩

一般什么时候会用到抽象工厂呢?

  • 如果想要创建的对象关联关系小,但是却具有相同的约束关系,那么就可以使用抽象工厂。
  • 系统中包含多个产品,但是一次只会用到一个产品,例如在本例中客户端不会既画矩形又画椭圆。
  • 系统只提供一个产品类的库,所有的产品会以同样的接口出现,从而客户端不依赖于具体实现。

最后

以上就是狂野项链为你收集整理的设计一个矩形类rectangle_TypeScript 设计模式与重构技巧 · 工厂模式的全部内容,希望文章能够帮你解决设计一个矩形类rectangle_TypeScript 设计模式与重构技巧 · 工厂模式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部