web-dev-qa-db-ja.com

単純なファクトリーとファクトリーメソッドの違いは何ですか?

単純なファクトリーとファクトリーメソッドについて少し混乱しています。私の主な困難は、多くのそれらがInterfacesを使用しているものやSwitch Casesを使用しているものや、 registers

PHPを使用してこの単純な1つの例を作成しましたが、それが単純なファクトリーまたはファクトリーメソッド、あるいはその両方と見なせるかどうか確信が持てません。

<?php

abstract class Log {
    protected $nome;     
    public function __construct(string $nome) {
        touch($nome);
        $this->nome = $nome;
    }

    protected function getDataHora(): string {
        return (new \DateTime())->format('Y-m-d h:I:s.v');
    }
    public abstract function insert(string $texto);
    public abstract function read(): string;
}

class TextLog extends Log {

    public function insert(string $texto) {
        $log_entry = $this->getDataHora() . ";" . $texto . PHP_EOL;
        file_put_contents($this->nome, $log_entry, FILE_APPEND | LOCK_EX);
    }

    public function read(): string {
        return file_get_contents($this->nome);
    }

}

class JsonLog extends Log {
    public function insert(string $texto) {
        $log_entry = ['data' => $this->getDataHora(), 'texto' => $texto];
        $json = file_get_contents($this->nome);
        $tempArray = json_decode($json, true);
        if(!is_array($tempArray)){
            $tempArray = [];
        }
        array_Push($tempArray, $log_entry);
        $jsonData = json_encode($tempArray);
        file_put_contents($this->nome, $jsonData);
    }

    public function read(): string {
        $json = file_get_contents($this->nome);
        $array = json_decode($json);
        return implode(";", $array);
    }

}

class LogFactory {
    public static function get(string $tipo): Log {
        switch (strtoupper($tipo)) {
            default:
            case 'TXT':
                return new TextLog("log.txt");
            case 'JSON':
                return new JsonLog("log.json");
        }
    }
}
$log = LogFactory::get('txt');
var_dump($log);
$log->insert('Testando 1,2,3...');
1
celsowm

考えてみましょう:

  • オブジェクトの直接作成、
  • シンプルな工場、
  • ファクトリーメソッド、
  • 抽象工場

直接オブジェクトを作成すると、newを介していくつかのクラスコンストラクターを直接呼び出すクライアントコードがあります。これにより、クライアントコードと作成されたクラスの間に強い結合が作成されます。他のクラスでクライアントを使用するということは、new操作が発生する場所にかかわらず、クライアントのコードを編集する(コードの複製と分岐)ことを意味します。 (クライアントコードは、特に同じプログラムで別のコンテキストで再利用できるほど抽象的であると想定すると、この編集は望ましくありません。)

単純なファクトリーは、オーバーライドまたは多態的に実装されるように設計されていないメソッドで、実際の呼び出し(newコンストラクターのインスタンス化)を隠します。そのため、単純なファクトリは多くの場合静的メソッドです。クライアントとクラス(コンストラクター)間の強い結合を、クライアントと静的なファクトリーメソッド間の強い結合と交換します。あるクラスの使用法を別のクラスに変更するためにクライアントで編集する必要がある場所の数を減らすための1レベルの間接指定。

ファクトリメソッドパターンはこれに基づいていますが、ポリモーフィズムによってファクトリメソッドを再実装する機能を追加します。したがって、パラメータとして渡すことができるファクトリオブジェクトの概念があります。同じプログラム内に複数の/異なるファクトリオブジェクトが存在する可能性があります。作成するさまざまなオブジェクトでクライアントコードを使用するためにクライアントを編集する必要はありません。代わりに、ファクトリのポリモーフィック実装を作成し、クライアントコードをそれらと共に使用できます。

抽象ファクトリパターンには、ファクトリメソッドの複数の実装が含まれているため、単一の抽象ファクトリで、必ずしも相互のサブクラスではない関連クラスを作成できます。これは、単に関連しているが異なるファクトリメソッドパターンの集合です。

これらのパターンはどれも、単に構築するコードから何を構築するかを決定するいくつかの距離コードで分離するまで、それほど意味がありません。後者は、具体的なクラスを作成するという決定を誤ってハードコードしない限り、再利用のために抽象化できることがよくあります。 (コードの1行でファクトリーを作成し、次のファクトリーでオブジェクトを作成すると、概念全体が打ち倒されますが、見つかる多くの例がそれを正確に実行します。)

ここで、依存関係の注入と制御の反転が行われます。アイデアは、構築するクラスの選択を、アルゴリズムがファクトリをパラメーターとして使用してオブジェクトを作成する再利用可能なクライアントコードから遠ざけることです。

3
Erik Eidt