Template Child(交给子类) 父类自动管理子类实例

一、Temlplate Child 交给子类设计模式定义

父类中定义流程的框架,在子类中具体实现。每个子类针对没件事情的做法可能不同,但是做的事情都一样。

二、需求

有时候业务需要自动识别满足一定规则下的所有的子类,并且根据指定标识分发业务数据到子类处理。

三、环境相关

语言: javascript

四、实现场景

  • 设计模式
    父类定义抽象方法,子类去实现。
  • 代码逻辑
  1. 定义每个实例的instanceId

  2. 父类TaskHandler中定义子类任务都需要做dealTask(哪些事情)

  3. 父类TaskHandler把任务的做法dealTask交给了子类

  4. 定义父类静态方法registInstance

    function TaskHandler (instanceId) {
      this.instanceId = instanceId
      this.registInstance = function () {
        // 子类调this是子类实例
        TaskHandler.registInstance.call(this)
      }
      // 每实例化调用一次就注册一次实例
      this.registInstance.call(this)

      // 空函数目的就是让子类自己决定
      this.dealTask = function () {}
    }

    // 定义父类静态方法 【注册】】 这个方法子类可以通过调用父类的this.registTask 间接调用
    TaskHandler.registInstance = function () {
      console.log("registTask", this)
      if (!TaskHandler.cacheInstance) {
        TaskHandler.cacheInstance = []
      }
      TaskHandler.cacheInstance.push(this);
    }

    // 定义父类静态方法 【发布】 这个方法只能由父类发动
    TaskHandler.triggerTasks = function (tasklist) {
      // tasklist可以是一个任务数组[task] or 也可以是一个任务task
      if (tasklist instanceof Array) {
        // 该做一堆事儿了哈
        tasklist.forEach(task => {
          TaskHandler.cacheInstance.forEach(instance => {
            instance.dealTask.call(instance, task)
          })
        })

      } else if (typeof tasklist === 'sting' && [...tasklist].length > 0) {
        // 做一件事儿哈
        TaskHandler.cacheInstance.forEach(instance => {
          instance.dealTask.call(instance, tasklist)
        })
      }
    }

复制代码
  1. 子类中调用registInstance,调用父类静态方法registInstance,自动注册实例到父类中,方便父类管理
    function EasyTask (instanceId) {
      this.instanceId = instanceId
      this.difficultType = 1 // 简单
      TaskHandler.call(this, this.instanceId)

      this.dealTask = function (taskName) {
        console.log(this.instanceId + '我是简单任务的做法,要开始干活儿啦', '任务名字是' + taskName)
        // ...
      }
    }

    function DifficultTask (instanceId) {
      this.instanceId = instanceId
      this.difficultType = 2 /// 困难
      TaskHandler.call(this, this.instanceId)

      this.dealTask = function (taskName) {
        console.log(this.instanceId + '我是困难任务的做法,要开始干活儿啦', '任务名字是' + taskName)
        // ...
      }
    }
复制代码
  1. 子类都注册好了实例之后,通过父类registInstance时间分发给子类处理各自的事情
    const easy = new EasyTask("小憨憨")
    const diffocult = new DifficultTask("大憨憨")

    TaskHandler.triggerTasks(['上树', '下树'])
    
    // 打印结果
     registTask EasyTask {
      instanceId: '小憨憨',
      difficultType: 1,
      registInstance: [Function]
    }
    registTask DifficultTask {
      instanceId: '大憨憨',
      difficultType: 2,
      registInstance: [Function]
    }
    小憨憨我是简单任务的做法,要开始干活儿啦 任务名字是上树
    大憨憨我是困难任务的做法,要开始干活儿啦 任务名字是上树
    小憨憨我是简单任务的做法,要开始干活儿啦 任务名字是下树
    大憨憨我是困难任务的做法,要开始干活儿啦 任务名字是下树
    
    // 
复制代码

五、小结

  • 无论在父类中使用哪一个子类的实例,都可以正常工作,这种思想是一个通用的继承原则,不仅限于Template Method
  • 我们想让哪个子类干活就注册哪个子类,然后让父类去派发他们。重新定义子类里边的方法,就可以改变程序的行为
  • Template Method中,方法调用逻辑定义在父类,子类就更加轻松,但是子类也就不灵活。如果父类定义的方法过少,子类就会臃肿,甚至子类间会有重复代码。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享