最初のメソッドの欠点は、呼び出しごとに新しいCityオブジェクトを作成することです。そのようなものは私にとってより自然なものになるでしょう:
class State
{
protected [City] capitalCity;
...
public [City] getCapitalCity()
{
if (this.capitalCity == null) {
this.capitalCity = City::getCapitalOf(this);
}
return this.capitalCity;
}
}
class City
{
...
public static [City] getCapitalOf(State s)
{
return new City(s.capitalCityID)
}
}
私は両方の方法をそのままにして、一方を他方に委任したことに注意してください。この変更後もまだ解決されていないもう1つの点は、Cityオブジェクトを交換できないことです。つまり、単体テストのモックと交換できません。依存関係は固定されています。
デザインパターンについて言えば、緩く結合されたデザインの場合、オブジェクトをインスタンス化するクラスはファクトリのみである必要があります。
ここでそれを適用すると、次のようになります。
class CityFactory
{
...
public static [City] createCapitalFromState(State s)
{
return new City(s.capitalCityID);
}
}
class State
{
protected [City] capitalCity;
...
public [City] getCapitalCity()
{
if (this.capitalCity == null) {
this.capitalCity = CityFactory::getCapitalOf(this);
}
return this.capitalCity;
}
}
class City
{
....
}
簡単にするために、ファクトリメソッドを静的に保ちました。実際には、のインスタンスにアクセスできますCityFactory
。そして、これは簡単に交換して、さまざまなオブジェクトを生成できます。
作成方法をどこに書くかを決める必要があるとき、私は自分自身に何を尋ねるべきですか?
2つのこと:
- 新しいハードワイヤード依存関係を導入しますか?
- オブジェクト作成を独自のクラスに抽出できますか?
2つのドメインオブジェクトは、明らかに常に一緒に使用されるため、デカップリング演習の最良の例ではないCity
と考えることができますか?State
しかし、あなたがそれについて考えるならば、それはそれほど大げさではありません:多分ある時点であなたは行動の特定の違いを区別するためにあなたの都市をサブクラス化または装飾するでしょう。シティファクトリを使用すると、都市の作成を変更したい場合に、一度に変更するだけで済みます。そして、これはOODの重要な目標です。何かを変更する必要がある場合、それをあちこちで変更する必要はなく、ある時点でのみ変更する必要があります。