1.オブジェクトと依存関係-DAO拡張


1.3 DAO拡張


前章では、「オブジェクト向けの世界では、ビジネスニーズに応じてオブジェクトの設計が変更される可能性があります.」言ったよ.
しかし、異なるオブジェクトには異なる変化の性質がある.
変化の性質の違いは、変化の理由、時期、周期などが異なることを意味する.
なぜ興味点を分離してコードを書くのですか?
これは変化の性質の異なるものを分けて、互いに影響しない場合、必要に応じて独立して変えることができるためです.

1.3.1クラス分離


前章では,継承による関心事項の分離について議論した.
今回は,注目点が異なり,変化の性質が異なるコードを完全に独立したクラスに分ける.
に道を教える
  • DB接続に関連する部分は、サブクラスではなく独立したクラスになります.
  • 以降は、このクラスをUserDaoに使用させておけばよい.
  • public class UserDao {
    
        private SimpleConnectionMaker simpleConnectionMaker;
    
    	// 상태를 관리하는 것도 아니닌 한번만 만들어 인스턴스 변수에 저장해두고 메소드에서 사용하게 한다.
        public UserDao() {
            this.simpleConnectionMaker = new SimpleConnectionMaker();
        }
        
        public void add(User user) throws ClassNotFoundException, SQLException {
            Connection c = this.simpleConnectionMaker.makeNewConnection();
        ...
        }
    
        public void get(String id) throws ClassNotFoundException, SQLException {
            Connection c = this.simpleConnectionMaker.makeNewConnection();
        ...
        }
    
    }
    DB接続の関心事とは独立したシンプルなConnectionMakerを以下に示します.
    public class SimpleConnectionMaker {
        public Connection getConnection() throws ClassNotFoundException, SQLException {
    
            Class.forName("com.mysql.cj.jdbc.Driver");
    
            // Connection 을 가져온다.
            Connection c = DriverManager.makeNewConnection(
                    "jdbc:mysql://localhost:3306/toby?useSSL=false", "root", "password"
            );
    
            return c;
    
        }
    }
    前述したように、機能に変化がないことを確認するために、コードを再コンパイルしてテストする必要があります.
    main()メソッドを再実行し、変更前と同じ結果が得られることを確認します.
    異なる変化特性を持つコードを独立したクラスに生成して分離することはよく行われているようだ.
    ただし,N社とD社にのみUserDaoクラスを提供し,拡張データベース接続機能を継承することで再利用できなくなった.
  • UserDaoのコードはSimpleConnectionMakerという特定のクラスに依存するためです.
  • すなわち,クラスが継承を利用するように自由に拡張できるようにするには,2つの問題を解決する必要がある.

  • クライアントごとに異なるメソッド名を使用してDB接続を取得する場合に発生する問題
  • makeNewConnection()メソッドを使用しましたが、クライアントは異なるメソッド名を使用できます.
  • の場合、makeNewConnection()に書かれているすべてのコードを変更する必要があります.

  • UserDaoはDB接続を提供するクラスが何であるかを具体的に知るべきである.
  • 1.3.2インタフェースの導入


    上記の問題の最良の解決策は、2つのクラス間の緊密な接続を回避するために、抽象的な緩やかな接続リングを中間に作成することである.
    インタフェース
  • Javaが提供する最も有用な抽象ツール
  • は、自分を表すクラスに関するすべての具体的な情報を非表示にします.
  • 抽象化:ある物事の共通性を抽出することによって、それを分離する仕事.
    次の図は、インタフェースを導入したクラスの関係を示しています.

    ConnectionMakerインタフェース
    public interface ConnectionMaker {
        public Connection makeNewConnection() throws ClassNotFoundException, SQLException;
    }
    ConnectionMaker実装クラス
    public class DConnectionMaker implements ConnectionMaker {
        public Connection makeNewConnection() throws ClassNotFoundException, SQLException {
        	// D 사의 독자적인 방법으로 Connection을 생성하는 코드
    	}
    }
    ConnectionMakerインタフェースを使用して改善されたUserDao
    public class UserDao {
    	
        // 인터페이스를 통해 오브젝트에 접근하므로 구체적인 클래스 정보를 알 필요가 없다.
        private ConnectionMaker connectionMaker;
    
        public UserDao() {
        	// 하지만! 여기에는 특정 클래스 이름이 나온다.
            this.connectionMake = new DConnectionMaker();
        }
        
        public void add(User user) throws ClassNotFoundException, SQLException {
            Connection c = this.connectionMaker.makeNewConnection();
        ...
        }
    
        public void get(String id) throws ClassNotFoundException, SQLException {
            Connection c = this.connectionMaker.makeNewConnection();
        ...
        }
    
    }
    UserDaoのadd()メソッド、get()メソッドおよびフィールドは、ConnectionMakerというインタフェースおよびインタフェースのmakeNewConnection()メソッドのみを使用します.
    したがって,N社とD社がDB接続クラスを再作成しても,UserDaoのコードを修正する必要はない.
    しかし、UserDaoのコードをよく見ると、DCConnectionMakerというクラス名が表示されます.
    UserDaoで特定のクライアントの情報を設定する必要があるコードもあります.

    1.3.3関係責任の分離の確立


    UserDaoには、クラスを実装するためにどのConnectionMakerを使用するかを決定するコードが残っています.
    これは,UserDaoに他の未分離の注目点が存在するためである.
  • ユーザデータとユーザデータが使用する接続マッパの特定の実施クラスとの関係
    この注目点をUserDaoから分離しないと、UserDaoは独立して拡張可能なクラスにはなりません.
    解決策
  • UserDaoのクライアントオブジェクトは、その注目点を分離するための適切な位置である.
  • UserDaoのクライアントでUserDaoを使用する前に、まずUserDaoにどのConnectionMaker実装クラスを使用するかを決定させます.
  • つまり、クラス間で関係を作成するわけではありません.オブジェクト間で動的な関係を確立します.
    クラスとクラスの関係:コードに異なるクラス名が表示されているため作成
    オブジェクト間の関係:コード内のクラスの名前が分からなくても、そのクラスのオブジェクトをインタフェースタイプとして受信して使用できます.
    これは,対象となる番組の多形性という特徴のおかげである.
    オブジェクト間の関係は、実行時点のオブジェクト間で生じる関係です.
    依存関係または実行時に使用される関係をリンクと呼びます.
    UserDaoのクライアント:main()
    UserDaoの作成者を変更し、クライアントが事前に作成した特定のクラスConnectionMakerのオブジェクトを受信するためのパラメータを追加します.
    変更された作成者
    public class UserDao {
    	
        // 인터페이스를 통해 오브젝트에 접근하므로 구체적인 클래스 정보를 알 필요가 없다.
        private ConnectionMaker connectionMaker;
    
        public UserDao(ConnectionMaker connectionMaker) {
            this.connectionMake = connectionMaker
        }
    }
    リレーショナル責任を確立するためのUserDaoクライアントmain()メソッドが追加されました
    public class main {
        public static void main(String[] args) throws SQLException, ClassNotFoundException {
        	// UserDao가 사용할 ConnectionMaker 구현 클래스를 결정하고 오브젝트를 만든다.
            ConnectionMaker connectionMaker = new DConnectionMaker();
    
    		// 1. UserDao 생성
            // 2. 사용할 ConnectionMaker 타입의 오브젝트 제공.
            //    결국 두 오브젝트 사이의 의존관계 설정
            UserDao userDao = new UserDao(connectionMaker);
    	}
    }
    UserDaoのクライアントとして、MainはUserDaoを変更せずにN社とD社のDB接続クラスを作成して使用しています.

    1.3.4原則とパターン


    これまでの超難関DAOコードの改善の結果を対象技術に対する種々の理論により説明しようとした.

    オープンクローズ原則OCP、Open-Closed Principle

  • クラスまたはモジュールは拡張時に開く必要があり、変更時に
  • を閉じる必要があります.
  • UserDaoは、DB接続方法を拡張する機能においてオープンである.
    ユーザデータに影響を及ぼさずに機能を拡張できます.
  • UserDaoコア機能を実現したコードは、これらの変化の影響を受けずにそのまま保持できるため、変更はクローズされる.
  • 高凝集低結合高コヒーレント低結合


    こうぎょうしゅうど
  • は、1つのモジュール、1つのクラスが1つの責任または注目点にのみ注目していることを示します.
  • が変化すると、モジュール(注目点が同じ)が大きく変化する
    ていけつごうど
  • 責任および関心のある他のオブジェクトは、回転するモジュールと低い結合度を維持したほうがよい.
  • より低い結合度は、間接的に関係を維持するために必要な最小限の方法を提供するだけである.
    残りは互いに独立することだ.
  • 戦略モードStrategy Pattern


    これは
  • の開放閉鎖の原則に最も合致するモデルである.
  • では、必要に応じて変更する機能をインタフェースから分離できます.
    これを実現する特定のクラスは、必要に応じて使用する設計モードを交換することができる.
  • ソース:github