简单工厂模式(常用)
- 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例;
- 简单工厂模式 优点:
- 只需要传入正确的参数,就可以获取需要的对象,无需知道创建细节;
- 工厂类中有必要的 判断逻辑,可以决定根据当前的 参数 创建对应的 产品实例,客户端可以免除直接创建产品对象的责任;
- 通过该模式,实现了对 创建实例 和 使用实例 的责任分割 ;
- 提供专门的工厂类用于 创建对象,客户端无需知道所创建的产品类的类名,只需要知道对应产品类的参数即可创建对象实例;
- 简单工厂模式 缺点:
- 工厂类职责过重,如果要增加新的产品,需要修改工厂类的判断逻辑,违背 “开闭原则”;
- 7 大设计原则,不能全部遵守,也不能不遵守,注意平衡功能和系统复杂度,找到最合适的一个点;
- 适用 场景:
- 创建对象少:工厂类 负责 创建的对象 比较少 ;
- 不关心创建过程:客户端 只知道 传入 工厂类 的参数,对于 如何创建对象 不关心;
类图
bad
class Plant {
constructor(name) {
this.name = name;
}
grow() {
console.log("growing~~~~~~");
}
}
class Apple extends Plant {
constructor(name) {
super(name);
this.taste = "甜";
}
}
class Orange extends Plant {
constructor(name) {
super(name);
this.taste = "酸";
}
}
// 直接 new 的缺点
// - 1. 耦合(需要知道具体的类在哪里)
// - 2. 依赖具体的实现(大量业务用到了 Apple 类,若之后要修改 Apple 会造成很多的问题)
new Apple();
new Orange();
good
class Plant {
constructor(name) {
this.name = name;
}
grow() {
console.log("growing~~~~~~");
}
}
class Apple extends Plant {
constructor(name) {
super(name);
this.taste = "甜";
}
}
class Orange extends Plant {
constructor(name) {
super(name);
this.taste = "酸";
}
}
// 简单工厂
class Factory {
static create(name) {
switch (name) {
case "apple":
return new Apple("苹果");
case "orange":
return new Orange("橘子");
}
}
}
let apple = Factory.create("apple");
console.log(apple);
let orange = Factory.create("orange");
console.log(orange);
经典场景
-
jQuery
class jQuery { constructor(selector) { let elements = Array.from(document.querySelectorAll(selector)); let length = elements ? elements.length : 0; for (let i = 0; i < length; i++) { this[i] = elements[i]; } this.length = length; } html() { } // ... } window.$ = function (selector) { return new jQuery(selector); }
-
React
class Vnode { constructor(tag, attrs, children) { this.tag = tag; this.attrs = attrs; this.children = children; } } React.createElement = function (tag, attrs, children) { return new Vnode(tag, attr, children); }
工厂方法模式
工厂方法模式 Factory Method,又称多态性工厂模式,在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做;
工厂方法模式 优点:
- 不关心创建细节:用户只需要关心 所需产品对应的工厂,无需关心 创建细节;
- 符合开闭原则:加入新产品,符合 开闭原则,提高 可扩展性;
工厂方法模式 缺点:
- 增加复杂性:类的个数容易过多,增加 系统复杂度;
- 在 添加新产品时,除了编写 新的产品类 之外,还要 编写该产品类对应的工厂类;
- 增加难度:增加了系统 抽象性 和 理解难度;
工厂方法模式适用 场景:
- 重复代码:创建对象 需要使用 大量重复的代码;
- 不关心创建过程:客户端 不依赖 产品类,不关心 实例 如何被创建,实现等细节;
- 创建对象:一个类 通过其 子类 来 指定 创建哪个对象;
类图
实现代码
class Plant {
constructor(name) {
this.name = name;
}
grow() {
console.log('growing~~~~~~');
}
}
class Apple extends Plant {
constructor(name) {
super(name);
this.taste = '甜';
}
}
class Orange extends Plant {
constructor(name) {
super(name);
this.taste = '酸';
}
}
class AppleFactory {
create() {
return new Apple();
}
}
class OrangeFactory {
create() {
return new Orange();
}
}
// 工厂方法模式中,使用工厂类创建产品对象,同时隐藏了具体的产品类被实例化的细节
const settings = {
'apple': AppleFactory,
'orange': OrangeFactory
}
let apple = new settings['apple']().create();
console.log(apple);
let orange = new settings['orange']().create();
console.log(orange);
抽象工厂模式
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式,抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象;
抽象工厂模式 优点:
- 隔离产品代码:在 应用层 隔离 具体产品的代码,客户端 无须关心 产品创建 的细节;
- 创建产品族:将 一个系列 的 产品族,统一到 一起创建;
抽象工厂模式 缺点:
- 扩展困难:规定了 所有 可能被创建的 产品集合,产品族中 扩展 新的产品 困难,需要 修改抽象工厂的接口;
- 增加难度:增加了系统的 抽象性 和 理解难度;
抽象工厂模式适用 场景;
- 忽略创建细节:客户端 不关心 产品实例 如何 被创建 实现等细节;
- 创建产品族:强调 一系列 相关的 产品对象,一般是 同一个产品族,一起使用 创建对象 需要大量 重复的代码;
- 产品类库:提供 一个 产品类 的库,所有的产品 以 同样的接口出现,使 客户端不依赖于具体实现;
类图
实现代码
class Button {
render() {
}
}
class AppleButton {
render() {
console.log('苹果按钮');
}
}
class WindowButton {
render() {
console.log('Windows按钮');
}
}
class Icon {
render() {
}
}
class AppleIcon {
render() {
console.log('苹果图标');
}
}
class WindowIcon {
render() {
console.log('Windows图标');
}
}
class Factory {
createButton() { }
createIcon() { }
}
class AppleFactory extends Factory {
createButton() {
return new AppleButton();
}
createIcon() {
return new AppleButton();
}
}
class WindowsFactory extends Factory {
createButton() {
return new WindowButton();
}
createIcon() {
return new WindowIcon();
}
}
const settings = {
'apple': AppleFactory,
'windows': WindowsFactory
}
let appleFactory = new settings['apple']();
appleFactory.createButton().render();
appleFactory.createIcon().render();
let windowsFactory = new settings['windows']();
windowsFactory.createButton().render();
windowsFactory.createIcon().render();
对比
-
简单工厂:一般就是一个函数返回产品的实例;
-
工厂方法:多了工厂类,想要创建产品,需要先创建此工厂的实例,再通过此工厂来创建实例;
-
抽象工厂:一个工厂可以创建多种产品;
设计原则
上一篇