https://mp.weixin.qq.com/s/YAiJTn1ESyb1mRrKxGdOKw
https://www.yuque.com/wubinhp/uxiv5i/kouxax#pUaQJ

在传统的面型对象语言中,一个运用了模板方法模式的程序中,子类的方法种类和执行顺序都是不变的,所以我们把这部分逻辑抽象到父类的模板方法中。而子类的方法具体怎么实现则是可变的,于是我们把这部分变化的逻辑封装到子类,我们便能给系统增加新的功能,并不需要改动抽象父类以及其他子类,这也是符合开放-闭合原则的。

定义:允许子类别为一个或多个步骤提供其实现方式。让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤。

用类实现

  1. /* 虚拟方法 */
  2. const abstractFunc = function () {
  3. throw new Error("抽象方法不能调用!");
  4. };
  5. /* 饮料方法 */
  6. class AbstractClass {
  7. constructor({
  8. operate2 = abstractFunc, // 抽象方法
  9. }) {
  10. this.operate2 = operate2;
  11. }
  12. /* 共用方法 */
  13. operate1() {
  14. console.log("operate1");
  15. }
  16. /* 模板方法 */
  17. init() {
  18. this.operate1();
  19. this.operate2();
  20. }
  21. }
  22. /* 实例 */
  23. const instance = new AbstractClass({
  24. /* 覆盖抽象方法 */
  25. operate2: function () {
  26. console.log("operate2");
  27. },
  28. });
  29. instance.init();
  30. // 输出:operate1
  31. // 输出:operate2

JS实现

  1. var father = function (params) {
  2. var step0 = function () {
  3. console.log("step0");
  4. };
  5. var step1 =
  6. params.step1 ||
  7. function () {
  8. return true;
  9. };
  10. var step2 =
  11. params.step2 ||
  12. function () {
  13. throw new Error("need step2");
  14. };
  15. var execute = function () {
  16. step0();
  17. if (!step1()) return;
  18. step2();
  19. };
  20. return execute;
  21. };
  22. var child = {
  23. step1() {
  24. console.log("step1");
  25. return true;
  26. },
  27. step2() {
  28. console.log("step2");
  29. },
  30. };
  31. var child1 = father(child);
  32. child1();

目的就是为了子类去实现父类的部分方法,父类按一定的逻辑调用方法。