规格模式 Specification Pattern
创始人
2024-02-11 01:57:34
0

Specification Pattern

不了解 SOLID 的可以扫一眼这个:SOLID,面向对象设计五大基本原则。

今天扫 SOLID JS 的时候,授课者对 OCP 的一个实现方式利用了 Specification Pattern,所以这里也进行一下补充学习。

不过讲道理来说,因为 JavaScript 是一个弱类型的语言,所以很难强制让子类去实现其他语言中 interface/abstract 的函数,这也是一个局限了。

使用案例为,假设需要实现一个过滤器(filter),最初的实现方式如下:

const COLOR = Object.freeze({RED: 'red',GREEN: 'green',BLUE: 'blue',
});const SIZE = Object.freeze({SMALL: 'small',MEDIUM: 'medium',LARGE: 'large',
});class Product {constructor(name, color, size) {this.name = name;this.color = color;this.size = size;}
}class ProductFilter {filterByColor(products, color) {return products.filter((p) => p.color === color);}filterBySize(products, size) {return products.filter((p) => p.size === size);}
}const apple = new Product('Apple', COLOR.GREEN, SIZE.SMALL);
const tree = new Product('Tree', COLOR.GREEN, SIZE.LARGE);
const house = new Product('House', COLOR.BLUE, SIZE.LARGE);const products = [apple, tree, house];const pf = new ProductFilter();console.log('Green products:');
for (const p of pf.filterByColor(products, COLOR.GREEN)) {console.log(` * ${p.name} is green.`);
}

可以看到之后如果要写其他的 filter,也是可以继续在 ProductFilter 实现的,不过这里有几个问题:

  1. 继续实现其他的 filter 就要修改现有的代码
  2. 每一次新的需求来了,都需要额外实现新需求,这会引起 state space explosion 的问题,毕竟 3 个变量的 AND 操作,就需要 7 个方法去进行实现(A, B, C, A+B, B+C, A+C, A+B+C)。

一个解决这个问题的方法是使用 specification pattern,修改代码如下:

// should be done through inheritance, but js doesn't reenforce inheritance
// class Specification {}class ColorSpecification {constructor(color) {this.color = color;}isSatisfied(item) {return item.color === this.color;}
}class SizeSpecification {constructor(size) {this.size = size;}isSatisfied(item) {return item.size === this.size;}
}class FilterSpecs {filter(items, spec) {return items.filter((x) => spec.isSatisfied(x));}
}const fs = new FilterSpecs();console.log('Green products with specs:');
for (const p of fs.filter(products, new ColorSpecification(COLOR.GREEN))) {console.log(` * ${p.name} is green.`);
}

对于 AND 操作的实现补充如下:

class AndSpecifications {constructor(...specs) {this.specs = specs;}isSatisfied(item) {return this.specs.every((x) => x.isSatisfied(item));}
}console.log('Large and green products:');
const specs = new AndSpecifications(new ColorSpecification(COLOR.GREEN),new SizeSpecification(SIZE.LARGE)
);for (const p of fs.filter(products, specs)) {console.log(` * ${p.name} is green and large.`);
}

使用 specification pattern 的优势就在于极大地减少了函数的实现,原本对于 AND 的操作,3 个条件就需要实现 7 个方法,而后如果有更多的需求,就需要些更多的方法去满足这些需求,对于 nnn 个需求来说,就会有 n+n−1,+...+1n + n-1, + ... + 1n+n−1,+...+1,也就是 n2n^2n2 个方法。。使用了 specification pattern 现在只需要实现 3+1 个,并且如果之后有其他的需求了,在实现对应的基类后,只需要调用 AndSpecifications 并将对应的 specs 传进去就行,换言之,只需要实现 n+1n+1n+1 个方法。

同样的,如果对 OR,XOR 操作也有需求,那么 specification pattern 就能省下大量的代码和开发时间。

Reference

  • Specification pattern

    wiki 上提供了不少的代码案例,包括 C#,Python,C++和 TS。

相关内容

热门资讯

“小包团”火了!哈尔滨“本地人... 文|王悦在哈尔滨老船厂社区,一家透着文艺气息的咖啡馆内,暖黄的灯光柔和地洒下,给木质桌椅都镀上了一层...
高晓峰:关税停滞后黄金重挫 空... 5月15日,金市场近期经历50小时震荡整理后选择向下突破,有效跌破3200整数关口,确认3浪下跌结构...
凭借三大核心技术,壁仞科技完成... 近日,在高效适配Qwen3系列模型推理后,壁仞科技宣布完成旗舰版Qwen3-235B-A22B模型的...
稳外贸扩消费,2025山东省外... 转自:大众报业·齐鲁壹点天朗气清,万物生辉,相聚好客山东,“质”享齐鲁。5月15日,由山东省商务厅、...
中银基金持续为投资者提供良好持... 为了践行社会责任,贯彻落实金融机构的政治性、人民性,构建保护公募基金投资者合法权益的良好生态,中银基...
印尼“三一一大学中国中心”正式...   中新网雅加达5月15日电 (记者 李志全)由中国西华大学与印尼三一一大学共建的“三一一大学中国中...
爆料:美国反对邀请泽连斯基参加... 转自:上观新闻据今日俄罗斯电视台网站5月14日报道,意大利安莎通讯社14日援引匿名外交消息人士的话说...
从红歌连奏到资源挖掘 文化艺术... 中新网三明5月14日电 (雷朝良)随着主持人一声令下,由十余位老知青组成的福州音梦电声乐队在福建省尤...
山东鄄城泰山石膏:“吞下”工业... 转自:经济日报走进山东鄄城县泰山石膏(菏泽)有限公司,智能化设备高效运转,一块块石膏板从生产线有序产...
第五届“临汾·520黄河英雄会... 转自:人民论坛以“文旅体+”开辟多元新业态助力乡村全面振兴,以激情赛事四县携手共同书写黄河流域生态保...
淮南市田家庵区发展和改革委员会... 转自:安徽纪检监察据安徽纪检监察消息,淮南市田家庵区发展和改革委员会主任李然涉嫌严重违纪违法,目前正...
代工期间抽检未通过 娃哈哈称已... 转自:消费日报官方微博 【代工期间抽检未通过 #娃哈哈称...
东来技术涨2.27%,成交额2... 5月15日,东来技术盘中上涨2.27%,截至14:19,报22.95元/股,成交2762.53万元,...
柳覃高速关键性工程加禄隧道顺利... 5月15日,由中铁二十局集团承建的广西柳州至覃塘高速公路全线最长隧道——加禄隧道顺利贯通,为后续线路...
汉商集团涨2.10%,成交额1... 5月15日,汉商集团盘中上涨2.10%,截至14:18,报8.77元/股,成交1.27亿元,换手率5...
多个区域手机自动接入信号! 北... 近日,北京不少市民发现手机右上角出现“5G-A”标识,伴随而来的是显著提升的网络速度,尤其是在一些人...
文明河北丨曲周公益红娘志愿服务... 转自:河北新闻网河北日报讯(记者赵泽众)近日,曲周县新成立了353支新时代公益红娘志愿服务队,实现县...
衢州发展跌2.25%,成交额1... 5月15日,衢州发展盘中下跌2.25%,截至14:03,报2.61元/股,成交1.32亿元,换手率0...
甘肃陇南:“流动蓝”翻越千重岭... 中新网兰州5月15日电 (高展 邓鹏银)陇南,地处甘肃东南部,秦巴山区、青藏高原与黄土高原在此交汇,...
张江高科跌2.02%,成交额3... 5月15日,张江高科盘中下跌2.02%,截至14:05,报25.21元/股,成交3.18亿元,换手率...