テンプレートメソッドパターンのつもりで、こんなクラスを作っておいて 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() の中をすっきりさせておくのは
コーディング規約に頼ることになってしまい、まだ心配の種は残る。