私は、PHPでファクトリパターンを実装する2つの異なる方法のうちの1つを考えています。私は、これらのバリアントが適切な名前を持っているかどうかわかりません。だから私はそれらを内部工場と外部工場と呼ぶつもりです。内部対外部の工場
内部ファクトリ:ファクトリメソッドは静的パブリックメソッドとしてクラス自体に実装され
<?php
class Foo
{
protected
$loadedProps = false;
public static factory ($id)
{
$class = get_called_class();
$item = new $class ($id);
if ($item -> loadedProps())
{
return ($item);
}
}
public function loadedProps()
{
return ($this -> loadedProps);
}
protected function loadPropsFromDB ($id)
{
// Some SQL logic goes here
}
protected function __construct ($id)
{
$this -> loadedProps = $this -> loadPropsFromDB ($id);
}
}
?>
外部工場:工場、それが初期化する項目は別個のエンティティとして実装さ
<?php
class Foo
{
protected
$loadedProps = false;
public function loadedProps()
{
return ($this -> loadedProps);
}
protected function loadPropsFromDB ($id)
{
// Some SQL logic goes here
}
public function __construct ($id)
{
$this -> loadedProps = $this -> loadPropsFromDB ($id);
}
}
abstract class FooFactory
{
public static factory ($id)
{
$item = new Foo ($id);
if ($item -> loadedProps())
{
return ($item);
}
}
}
?>
今はそれぞれがそのメリットを持っているようです。
前者では、外部からコンストラクタを非表示にすることができます。つまり、Fooオブジェクトを作成する唯一の方法は、工場を経由することです。アイテムの状態をDBからロードできない場合、ファクトリはNULLを返します。このNULLはコードで簡単に確認できます。
if ($item = Foo::factory ($id))
{
// ...
}
else
{
// The item failed to load. Handle error here
}
工場は、変更を加えずにFooの任意のサブクラスのオブジェクトを作成することもできます。
ただし、いくつかの欠点があるようです。まずクラスはファクトリを実装しなければなりません。ファクトリは実際に他のクラスに属するクラスに責任を負わせるかもしれません。内部の工場のバージョンは、確かに外部の工場のバージョンよりも大きなクラスになります。
外部の工場については、工場はクラスそのものではないので、きれいだし、もっと責任を負うクラスについて心配する必要はありません。外部ファクトリは依存性注入により適しています。
ただし、独自の欠点があります。まず第一に、PHPがパッケージの概念を持たず、クラスメンバのための「パッケージ」保護レベルもないため、工場で構築されるアイテムのコンストラクタはpublicでなければなりません。つまり、新しいFoo()を実行して工場をバイパスするだけで、コーダーが停止することはありません(ユニットテストは簡単になります)。
もう1つの問題は、FooFactoryはFooオブジェクトのみを作成でき、サブクラスは作成できないことです。これはFooFactoryに別のパラメータを追加してクラス名を指定することで回避できますが、工場では指定されたオブジェクトクラスがFooの子孫であるという内部チェックを行う必要があります。
基本的に、2つのアプローチの相対的なメリットは何ですか?どのようなものをお勧めしますか?
また、社内外の工場よりも固有の名前がある場合は、それらを知りたいと思います。
「オフトピック:」ランダムなメモでは、同じユーザー名を持つときに、両方とも同じことを話していることがユーモラスなことが分かります。もう一度私はあなたと話していると思った。 – Tek
@Tekええ、ゴードンはゴードンに答える。しかし、私はGordon™です:) – Gordon