ここでコードを疎結合するには、覚えておくべきいくつかの簡単なことがあります。
パート1:
技術的には「懸念の分離」として知られています。各クラスには特定の役割があり、ビジネスロジックまたはアプリケーションロジックを処理する必要があります。両方の責任を兼ね備えたクラスを避けてください。つまり、データを管理する(広義の)クラスはアプリケーションロジックであり、データを使用するクラスはビジネスロジックです。
個人的に私はこれを(自分の小さな世界では)と呼んでいcreate it or use it
ます。クラスはオブジェクトを作成するか、両方を実行しないオブジェクトを使用する必要があります。
パート2:
関心の分離を実装する方法。
出発点として、2つの簡単な手法があります。
注:設計パターンは絶対的なものではありません。
それらは状況に合わせてカスタマイズされることになっていますが、すべてのアプリケーションに似た基礎となるテーマを持っています。ですから、以下の例を見て、厳密にこれに従う必要があると言ってはいけません。これらは単なる例です(そして、少し工夫されています)。
依存性注入:
これは、クラスが使用するオブジェクトを渡す場所です。インターフェースに基づいて渡すオブジェクト。これにより、クラスはそれをどう処理するかを認識しますが、実際の実装を知る必要はありません。
class Tokenizer
{
public:
Tokenizer(std::istream& s)
: stream(s)
{}
std::string nextToken() { std::string token; stream >> token;return token;}
private:
std::istream& stream;
};
ここで、ストリームをTokenizerに注入します。トークナイザーは、std :: istreamのインターフェースを実装している限り、ストリームのタイプを認識しません。
サービスロケーターパターン:
サービスロケーターパターンは、依存性注入のわずかなバリエーションです。使用できるオブジェクトを与えるのではなく、使用したいオブジェクトを見つける(作成する)方法を知っているオブジェクトを渡します。
class Application
{
public:
Application(Persister& p)
: persistor(p)
{}
void save()
{
std::auto_ptr<SaveDialog> saveDialog = persistor.getSaveDialog();
saveDialog.DoSaveAction();
}
void load()
{
std::auto_ptr<LoadDialog> loadDialog = persistor.getLoadDialog();
loadDialog.DoLoadAction();
}
private:
Persister& persistor;
};
ここでは、アプリケーションオブジェクトに永続オブジェクトを渡します。保存/読み込みアクションを実行すると、永続化機能を使用して、アクションの実行方法を実際に知っているオブジェクトが作成されます。注:再び永続化はインターフェースであり、状況に応じて異なる実装を提供できます。
これはpotentially
、アクションをインスタンス化するたびに一意のオブジェクトが必要な場合に便利です。
個人的には、これは単体テストを書くのに特に役立つと思います。
パターンの注意:
デザインパターンは、それ自体が大きなテーマです。これは、疎結合を支援するために使用できるパターンの排他的なリストではありません。これは一般的な出発点です。
経験を積むと、正式な名前を使用しなかったというだけで、これらのパターンを既に使用していることに気付くでしょう。彼らの名前を標準化することで(そして誰もがそれらを学べるようにすることで)、アイデアを伝えることは簡単で迅速であることがわかります。