3

私は依存性注入を理解しようとしており、進歩を遂げていますが、

これらのコードの利点/違い/重要性を知りたいです。同じように見えますが、アプローチが異なります

//dependency injection - (as was claimed)
Customer customer = new Customer(10);

IOrderDAO orderDAO = new OrderDAO();
customer.setOrderDAO(orderDAO);
customer.getOrdersByDate();

また

//Unknown Pattern - Please what pattern is this?
Customer customer = new Customer(10);
IOrderDAO orderDAO = new OrderDAO();
orderDAO.getOrderByDate(customer.id);

2番目のアプローチの何が問題になっていますか?

ありがとう。

4

4 に答える 4

3

どちらも適切な依存性注入の例ではありません。これらはデータ アクセス パターンの例です。

最初のものは、アクティブなレコード パターンの例です。orderDAO を顧客エンティティの依存関係として設定すると、プロパティまたはセッターの注入を呼び出すことができます。

2 番目の例は、リポジトリ パターンです。ここでの依存関係パターンはメソッド インジェクションであり、いくつかのパラメーターを使用した一般的な呼び出しメソッドに変換されます (ここでのパラメーターはメソッドの依存関係です)。

DI パターンの学習を開始するには、この本を読むことをお勧めします。これらのビデオのような多くのオンライン リソースもあります。

Google で Dependency Inversion Principle を探すこともお勧めします (依存関係の注入とは異なります)。

于 2012-06-03T15:04:43.390 に答える
3

どちらも依存性注入のようには見えません。への呼び出しがあってはなりませんnew

依存性注入は、すべての依存性と結び付けられた Bean ファクトリによって行われます。Bean をインスタンス化し、依存関係を与えます。

ここには豆工場がまったく見えません。依存性注入への長い道のりです。

Customer は、setter を使用して最初の例で OrderDAO を取得します。最初のものは、顧客がその API で永続化メソッドを公開する必要があることを示しています。注文を保存する責任があります。顧客は注文について知る必要があるため、懸念の分離が不十分だと思います。

2 つ目は、Customer を OrderDAO から分離します。顧客 ID を OrderDAO に渡し、その顧客に代わって注文を保存します。私はそれが懸念のより良い分離だと思います。

しかし、どちらも依存性注入の良い例ではありません。

DI の最初で最も適切な記述は、Martin Fowler によるものです。これを注意深く読むことをお勧めします:

http://martinfowler.com/articles/injection.html

8年経ちますがまだまだ元気です。

于 2012-06-03T13:57:34.457 に答える
1

制御の反転と依存性注入を混同しないでください(別の回答のように)。ここで依存性注入とIoCについて説明します:http://www.codeproject.com/Articles/386164/Get-injected-into-the-world-of-inverted-dependenci

//dependency injection - (as was claimed)
Customer customer = new Customer(10);

IOrderDAO orderDAO = new OrderDAO();
customer.setOrderDAO(orderDAO);
customer.getOrdersByDate();

いいえ、そのDIとは呼びません。私はそれをひどく書かれたコードと呼ぶところまで行きます。setOrderDAO(orderDAO)顧客は、それを強制する永続化レイヤーを認識してはなりません。顧客も注文を処理する必要があるため、単一責任の原則に違反します。

//Unknown Pattern - Please what pattern is this?
Customer customer = new Customer(10);
IOrderDAO orderDAO = new OrderDAO();
orderDAO.getOrderByDate(customer.id);

customerこれは特定のパターンではありませんが、との間に結合がないため、より良いコードですorderDao

于 2012-06-11T12:18:45.600 に答える
1

これは奇妙な例ですが、最初の例は依存性注入コンテナーが行うことを示し、2 番目の例は1 つのオブジェクトが別のオブジェクトに引数を渡すことを示しています。1 つ目は、その依存関係を呼び出し元クラスのインスタンス変数として埋め込みます。2 つ目は、本質的に手続き型です。それ自体はどちらも間違っていません。依存関係の複雑さとコードの管理方法によって異なります。

あなたが提供したインジェクター コードを見るだけでは、依存性注入を使用したい理由はすぐにはわかりません。しかし、もう少し複雑な (そしてより典型的な) 例を考えてみましょう。

顧客サービス:

public class CustomerService implements ICustomerService {
    private IOrderDAO orderDao;

    public void setOrderDAO(IOrderDAO orderDao) {
        this.orderDao = orderDao;
    }

    public Order getOrderByDate(Integer customerId, Date date) {
        return this.orderDao.findOrderByDate(customerId, date);
    }
}

OrderDAO (デフォルトの実装):

public OrderDAO implements IOrderDAO {
    private javax.sql.DataSource dataSource;

    public void setDataSource(javax.sql.DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Order findOrderByDate(Integer customerId, Date date) {
    ...
    }
}

StubOrderDAO (スタブ実装):

public StubOrderDAO implements IOrderDAO {

    public Order findOrderByDate(Integer customerId, Date date) {
      return new HardCodedOrder(); // this class would extend or implement Order
    }
}

実行時に、 のインスタンスは、CustomerServiceどの IOrderDAO の実装が使用されているかわかりません。これは、たとえば、CustomerService の単体テストを初期化することで非常に簡単にブートストラップできることを意味しますStubOrderDAO(常にハードコードされた顧客を返します)。同様に、DataSource の実装も異なる場合があります (モック データ ソースか、異なるランタイム環境で異なるデータ ソースのいずれか)。

したがって、本番用のインジェクターは次のようになります。

// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new OrderDAO();
javax.sql.dataSource dataSource = jndiContext.lookup("java:comp/env/MyDataSource");

// initialize
dao.setDataSource(dataSource);
service.setOrderDAO(dao);
return service;

一方、ローカル (テスト) データ ソースを使用するためのインジェクターは次のようになります。

// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new OrderDAO();
javax.sql.dataSource dataSource = new DriverManagerDataSource("jdbc:sqlserver:yadayada...", "myUsername", "myPassword");

// initialize
dao.setDataSource(dataSource);
service.setOrderDAO(dao);
return service;

統合テスト用のインジェクターは次のようになります。

// instantiate
CustomerService service = new CustomerService();
OrderDAO dao = new StubOrderDAO();

// initialize
service.setOrderDAO(dao);
return service;

したがって、これは基本的に、適切な階層化と関心の分離を実装する方法です。つまり、データベースにアクセスする方法は、ドメイン モデルを作成するためにデータにアクセスする方法とは無関係であり、どちらも、実行する集計またはビジネス ロジック処理とは無関係です。でCustomerService(簡潔にするためにここには示していません)。

それはもっと理にかなっていますか?

于 2012-06-05T19:29:24.557 に答える