プロフィール

Blog

Template Methodパターン

使いどころ

  • 複数のクラスで共通の処理を行いたい
  • 決まった手順で処理を実行したい

TemplateMethodパターンは、抽象クラスに共通の処理であるテンプレートメソッド(AbstractAnimalクラスのcryVoice())を定義することにより、実現されます。

ソースコードを見てわかる通り、定義されているメソッドが同じかつ、そのメソッド達の実行手順が決まっているサブクラスを複数作成したい時に便利です。抽象クラスにテンプレートメソッドしてまとめるので、各サブクラスで同様の処理が重複するなどのリスクが低下します。また実行したい処理がまとまっているので、可読性が増します。

ただ単に処理を抽象クラスで共通化するだけではなく、「処理の共通化かつ、共通化した処理の実行順も共通化させる」ということが重要です。

しかしテンプレートメソッドで使用する抽象メソッドが増えれば増えるほど、複雑になり、冗長になるので注意が必要そうです。

ソースコード

AbstractClass(抽象クラス)

AbstractAnimal.php

抽象クラスには、テンプレートメソッド(cryメソッド)と抽象メソッドがあります。抽象メソッドの具体な処理は、具象クラスの方でオーバーライドします。実際に実行ファイルから呼ばれる処理はこのテンプレートメソッドになります。

<?php

abstract class AbstractAnimal {
    abstract public function start();

    abstract public function cryVoice();

    abstract public function end();

    // finalキーワードはオーバーライドさせない為に使用
    // 5回泣いてもらう
    final public function cry() {
        $this->start();
        for ($i = 0; $i < 5; $i++) {
            $this->cryVoice();
        }
        $this->end();
    }
}

ConcreteClass(具象クラス)

Dog.php

抽象クラスを継承して使います。抽象クラスで実装されている抽象メソッドをオーバーライドして、具体的な処理を実装します。

以下では、コンストラクタで受け取った引数(動物の鳴き声)を画面上に出力する予定です。

<?php
require_once __DIR__."/AbstractAnimal.php";

class Dog extends AbstractAnimal {
    private $voice;

    function __construct($voice) {
        $this->voice = $voice;
    }

    public function start() {
        echo "犬:";
    }

    public function end() {
        echo "<br>";
    }

    public function cryVoice() {
        echo $this->voice;
    }
}

Cat.php

<?php
require_once __DIR__."/AbstractAnimal.php";

class Cat extends AbstractAnimal {
    private $voice;

    function __construct($voice) {
        $this->voice = $voice;
    }

    public function start() {
        echo "猫:";
    }

    public function end() {
        echo "<br>";
    }

    public function cryVoice() {
        echo $this->voice;
    }
}

出力結果

参考:

「数値化の鬼」を読んだ

著者情報
安藤広大
株式会社識学 代表取締役社長
29万部を突破したベストセラー『リーダーの仮面』の著者

どんな人におすすめか?

・会社の目標設定でいつも悩む人
・方法もわからずなんとなく目標設定をしてしまっている人
・年始に立てた目標がいつも未達で終わってしまう人

なぜ数値化が必要なのか?

数値化することにより現状を知ることができ、それらを分析(強みや不足の理解)して、新たな目標設定をする為

まずは自分の現状を知ろう

立てた目標を達成する為には、今なにが不足していて、それがなぜ不足しているのかを知る必要があります。そして、今自分が行っている行動がその不足を補う為に正しく向かっているのか、今の行動量で期限までに達成可能なのかを見積もらなければいけません。

その為に、以下項目を管理し、把握し、分析していく必要があります。

・行動量
・作業の方向性
・作業の限界量

業種によっては数値化が難しい場合もあるが、上記を可視化できるようその為の指標を見つけ、管理することが大切です。

例) エンジニアの場合
・本番でのバグ回数
・期限遵守率
・タスクの消化数(タスク毎にポイントを割り振って、ポイント制にするのもあり)
・他部署への質問・調査しにいった回数(業務改善)

エンジニアもここは難しいなと思うところではあります。

指標はある程度決まったものもありますが、4つ目みたいなオリジナルを管理し、データを取っていくことも新たな発見があって楽しいのかもしれないです。

目標を立てっぱなしにしていないか?

僕は正直立てっぱなしでした。いつも大きな目標は立てるけど、小さな目標を別途管理していたかと言われれば、できていません。

決めた指標を日単位で管理(できてもここまで)し、週単位でその見直しをすること。結局ここができていないので、日々管理している指標がただの作業となり、「なんでこの指標取ってるんだっけ?」みたいになって、振り返りしないのでなにも改善されないまま月日は経ち、結局また目標が未達だったとなっているなと思いました。

プライベートにおいては、指標も管理してません。。。年始に立てた目標はこうなりがち。

変数という考え方

「仕事のどこを変えればいいのか」これを考えるのが仕事の醍醐味であると著書では述べています。

この「どこ」が変数です。

この変数にいち早く気づけるプレーヤーこそが「仕事ができる人」であり、上司に言われる前に、自分で考えれるようになることが本書の目的と書かれています。

目標に対して、指標を見つけ、管理・分析し、また新たな変数を見つける。そしてその変数を検証してみる。このPDCAを回すことが大事。

みんな頭ではわかっていることですよね。きっと。

これが「わかる」と「できる」は違うみたいなことなのかなと思いました。(最近会社でよく聞く言葉)

「当たり前とされていること」を「当たり前に続ける」って本当に難しいことです。

最後に

立てた大きな目標に対して、小さな目標を立てるみたいなことは今まで計画段階では、やっていたつもりでした。ですが、この著書を読んで、私が1番改善すべき点は指標の管理と分析だと感じました。

目標を立てっぱなしというのも自分の話で、かなりレベルが低く情けない話ですが、これが現実です。

今回会社の四半期の目標から見てもそう伺えます。

不足を受け止めて、指標の選定・管理する方法から改善していきたいと思います。

話しは変わりますが、
最近「仕事の本質は問題解決」だと改めて教えて頂きました。
そして、PDCAのP(目標)を考えるより前になによりも重要だなと思うことがあります。

それは「仕事相手が求めていることを正しく理解し、把握する」ということです。

ここが間違っていたら、どれだけ素晴らしいPDCAを回しても、絶対に良い結果となりませんよね。。。

以下のようなことを教えて頂いたのですが、私はまだまだ程遠いレベルにいる。。。

・相手が問題定義している理由を正しく理解し、把握すること
・相手が問題定義している内容が本当に解決しなければいけない問題なのか自分でも確認すること
・実は表面上にでてきていないだけで潜在ニーズが存在する可能性もある

どんな仕事をするにおいて絶対に必要なことなので、少しづつ学んでいきます

次はこの本読んでみます

Adapterパターン

Adapterパターンとは?

adapterとは「適合させる」という意味を持ち、既存のクラスのままではそのまま使えない場合などに、ターゲットの既存クラスをラッピングし、使える形に変える変換器のようなクラスのことを指します。別名でWrapperパターンとも言われます。

現実世界で例えるとこんな感じ。コンセントからPCに電気を供給するには、ACアダプタが必要です。なぜ必要かというと、コンセントから供給されている交流電圧ではPCは動かない為です。PCなどの一般機器は直接電圧である必要があります。コンセントから受け取った電圧を交流から直流に変換する為に、ACアダプタが必要とされています。

今回のパターンでは、二つの対象物をつなぐ役割をするインターフェースを実装することになります。

このパターンのなにがいい?

影響範囲が大きい未知数の既存クラスを改修(主に追加機能開発など)する際に、効果をもたらします。改修対象となるクラスに新規でインターフェースを実装し、そのインターフェースを実装したクラスを作成します。そのクラスを使用することにより、既存クラスを触ることなく必要な改修を行えるので、既存クラスの呼び出し先の影響範囲を考慮する必要がなくなり、テストケースが減ります。つまり、より安全に改修が可能になります。

クラス設計

今回は二つの対象物をつなぐためのインターフェースを作るだけになります。作成方法としては以下2パターンがあります。

  • 委譲するパターン
  • 継承するパターン

そもそも「委譲」と「継承」とは?

「継承」はなんとなくイメージできる人も多いと思いますが、「委譲」はどうでしょうか?

委譲

「委譲」は他者に権限や権利をゆだねるという意味で、英語では「delegate」といいます。

プログラムの世界では、クラスの一部の機能の実装を他のクラスに任せることを「委譲」といいます。

継承と委譲の違い

既存クラスの機能をどこまで使うかというのがポイントになるようです。

「継承」では、親クラスの全ての機能を子クラスが引き継ぎます。

「委譲」では、親クラスの一部を子クラスが引き継ぎます。

サンプルプログラム(継承を利用したパターン)

Adaptee

class Banner
{
    private $string;

    public function __construct($string)
    {
        $this->string = $string;
    }

    public function showWithParen()
    {
        echo "(" . $this->string . ")";
    }

    public function showWithAster()
    {
        echo "*" . $this->string . "*";
    }
}

Target

interface Print
{
    public function printWeak();

    public function printStrong();
}

Adapter

class PrintBanner extends Banner implements Print
{
    public function __construct($string)
    {
        parent::__construct($string);
    }

    public function printWeak()
    {
        $this->showWithParen();
    }

    public function printStrong()
    {
        $this->showWithAster();
    }
}

Client

class Main
{
    public function main()
    {
        $ob = new PrintBanner ("hoge");
        $ob->outputWeak();
        $ob->outputStrong();
    }
}
タイトルとURLをコピーしました