ファクトリパターンの利点は、使用方法から構造と特定のタイプの詳細をカプセル化することです。これにより、変更を加える場所を減らして、後でより興味深いデザインに進化させることができます。
この例を考えてみましょう。
public interface IStorage
{
void Save(SomeObject toSave);
SomeObject Get(SomeId id);
}
public class DatabaseStorage : IStorage
{
public void Save(SomeObject toSave)
{
//persist to DB somehow
}
public SomeObject Get(SomeId id)
{
//get from db somehow and return
}
}
public class StorageFactory
{
public IStorage GetStorage()
{
return new DatabaseStorage();
}
}
public class DatabaseStorage : IStorage
{
public void Save(SomeObject toSave)
{
//persist to DB somehow
}
public SomeObject Get(SomeId id)
{
//get from db somehow and return
}
}
ここで、後でいくつかの結果をキャッシュするか、すべての結果をログに記録する必要があると想像してください。次のようなプロキシを作成できます。
public class LoggingStorage : IStorage
{
private readonly IStorage _proxied;
public LoggingStorage(IStorage proxied)
{
_proxied = proxied;
}
public void Save(SomeObject toSave)
{
//log this call
_proxied.Save(toSave);
}
public SomeObject Get(SomeId id)
{
//log this call
return _proxied.Get(id);
}
}
さて、コンストラクターを使用した場合、これでラップするには、コンストラクターを使用するたびに置き換える必要があります。工場を使用した場合は、変更するだけです。
public class StorageFactory
{
public IStorage GetStorage()
{
return new LoggingStorage(new DatabaseStorage());
}
}
もちろん、投機的なファクトリはこれに対して少し手間がかかるように見えることがあります。そのため、コンストラクターをカプセル化することを好みます。