これにより、いくつかのことが解決される場合があります。
UML 矢印の説明
画像は Visual Studio のものですが、ほとんどの情報はほとんどの UML ドキュメントと同等であると思います。
破線は「implements」に相当するものを表します
UML でのエンティティの命名にも少し戸惑っています...Policy
の下位レベル モジュールへのコントラクトを記述するインターフェイスに依存しているようですMechanism
ただし、継承を表すと思われる2番目(実線)では(少なくとも私は信じています)。 具体的な参照時に DIP を適用する前ではなくMechanism
、インターフェイス (抽象化) を実装します。Policy
Policy
Mechanism
主に伝えようとしているのは、クラスは他のクラスに依存してはならないということですが、具象ではなく抽象化 (インターフェース) に依存することはできます。
これの最も簡単な例: 下位レベルのモジュールに依存する元の Foo/Logger。
// "Low level Module" Mechanism equivilant
public class Logger {
public void logInformation(String logInfo) {
System.out.println(logInfo);
}
}
// "High level module" Policy equivalent.
public class Foo {
// direct dependency of a low level module.
private Logger logger = new Logger();
public void doStuff() {
logger.logInformation("Something important.");
}
}
上記でFoo
は、 の具体的な実装に依存していLogger
ます。これはそのままリファクタリングできます (これを行う方法はいくつかありますが、これは 1 つにすぎません)。
public interface ILogger {
void logInformation(String logInfo);
}
public class Logger implements ILogger {
@Override
public void logInformation(string logInfo) {
System.out.println(logInfo);
}
}
public class Foo {
private ILogger logger;
public void setLoggerImpl(ILogger loggerImpl) {
this.logger = loggerImpl;
}
public void doStuff() {
logger.logInformation("Something important.");
}
}
このリファクタリングでFoo
は、 は に依存しなくなりましLogger
たが、インターフェイスを利用するILogger
ようになりました。つまり、実行時やオブジェクトのインスタンス化などで ILogger の実装を切り替えることができます。
あなたはそのように消費することができますFoo
:
Foo foo = new Foo();
ILogger logger = new Logger();
foo.setLoggerImpl(logger);
foo.doStuff();
もちろん、これはコンソールに「重要な何か」と出力されます。コンソールにログを記録するのではなく、データベースにログを記録したい場合はどうなるでしょうか。
public class LoggerToDb implements ILogger {
@Override
public void logInformation(string logInfo) {
DbContext databaseContext = new DbContext();
databaseContext.insertLog(logInfo);
}
}
次のように使用できるようになりました。
Foo foo = new Foo();
ILogger logger = new LoggerToDb();
foo.setLoggerImpl(logger);
foo.doStuff();
に依存していないFoo
ため、実装を変更する必要がなかったことに注意してください。代わりに、このアプローチを使用すると、抽象化に新しい具象を提供し、触れることさえせずにそれを交換できます。かなりニートIMO。Foo
Logger
ILogger
Foo
Foo
上記の例では、オブジェクトを構築して実装を提供していることに注意してください。これは、Java の Spring などの IOC フレームワークでも実行できます。