blog.fuktommy.com

テンプレートメソッドパターンのつもりで、こんなクラスを作っておいて class Foo { protected function doSomething() { // 複雑な処理 } publi...

テンプレートメソッドパターンのつもりで、こんなクラスを作っておいて

class Foo
{
  protected function doSomething()
  {
    // 複雑な処理
  }

  public function run()
  {
    // 略
    $this->doSomething();
    // 略
  }
}

基本的にはdoSomething()でいいんだけど、
子クラスによってはちょっと変わった動作をさせたい。
ただしdoSomething()は複雑な処理で、今後も変更がありそうだから、

class FooChild
{
  protected function doSomething()
  {
    // 前処理
    parent::doSomething();
    // 後処理
  }
}

みたいに必ず Foo#doSomething() を呼ぶというコーディング規約で縛っとこう。
と思ったが、現実にはコーディング規約は無視され、

class FooChild2
{
  protected function doSomething()
  {
    // Foo#doSomething()をコピペして改造した処理
  }
}

となるはず。
んで Foo#doSomething() を変更したときFooChild2も変更しなきゃとなって死ぬ。
そこで考えた。

abstract class Bar
{
  public function preSomething(Context $context) {}
  public function postSomething(Context $context) {}
}

関数の形式として前処理、後処理として縛ってしまう。

class Foo
{
  private function doSomething(Context $context)
  {
    // 略
    if ($context->todoHoge) {
      $this->doHoge();
    }
    // 略
  }

  public function run(Bar $bar, Context $context)
  {
    // 略
    $bar->preSomething($context);
    $this->doSomething($context);
    $bar->postSomething($context);
    // 略
  }
}

必要があれば$contextの中にフラグを用意して、
Foo#doSomething()の中でif文なりで動作を切り替える。

ただし Foo#doSomething() の中をすっきりさせておくのは
コーディング規約に頼ることになってしまい、まだ心配の種は残る。
Copyright© 1998-2014 Fuktommy. All Rights Reserved.
webmaster@fuktommy.com (Legal Notices)