Burninghering's Blog
article thumbnail

인터페이스를 활용한 다형성 구현 (dao 구현하기)

1. 인터페이스와 다형성

  • 하나의 인터페이스를 여러 객체가 구현하게 되면 클라이언트 프로그램은 인터페이스의 메서드를 활용하여 여러 객체의 구현을 사용할 수 있음 ( 다형성)
  • 여러가지 예

Sorting에는 다양한 방식이 있다 - 다형성
하나의 솔루션(UserInfoDao)에서 replace가 가능함(3개의 DB)

똑같은 인터페이스를 통해서 하나를 호출하지만, 여러 개의 인스턴스를 사용 가능 

똑같은 코드가 여러 개의 임플리멘테이션(구현)을 가지는 것이 다형성!

 

2. 인터페이스를 활용한 dao 구현하기

  • DB에 회원 정보를 넣는 dao(data access object)여러 DB 제품이 지원될 수 있게 구현함
  • 환경파일(db.properties) 에서 database의 종류에 대한 정보를 읽고 그 정보에 맞게 dao 인스턴스를 생성하여 실행될 수 있게 함
  • 패키지가 갖는 계층 구조를 source hierachy 라고 함 

UserInfo.java (사용자 정보 클래스)

package ch13.domain.userinfo;

public class UserInfo {
	
	private String userId;
	private String password;
	private String userName;
	
	//private로 변수들 선언했으므로 getter/setter 만들어주기
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}	
}

 

UserInfoDao.java ( dao 에서 제공되어야 할 메서드를 선언한 인터페이스 )

package ch13.domain.userinfo.dao;

import ch13.domain.userinfo.UserInfo; //import 해오기

public interface UserInfoDao {

	//유저 정보 DB 조작을 할 때, 구현해야 하는 기능은 아래와 같다고 선언하는 것이다.
	
	void insertUserInfo(UserInfo userUnfo);
	void deleteUserInfo(UserInfo userUnfo);
	void updateUserInfo(UserInfo userUnfo);
}

 

UserInfoMySqlDao.java (UserInfoDao 인터페이스를 구현한 MySql 버전 dao)

package ch13.domain.userinfo.dao.mysql;

import ch13.domain.userinfo.UserInfo;
import ch13.domain.userinfo.dao.UserInfoDao;

public class UserInfoMySqlDao implements UserInfoDao{

	@Override
	public void insertUserInfo(UserInfo userInfo) {
		System.out.println("Insert into MySQL DB user ID= " + userInfo.getUserId());
	}

	@Override
	public void deleteUserInfo(UserInfo userInfo) {
		System.out.println("Delete from MySQL DB user ID= " + userInfo.getUserId());
	}

	@Override
	public void updateUserInfo(UserInfo userInfo) {
		System.out.println("Update into MySQL DB user ID= " + userInfo.getUserId());
	}
}

 

UserInfoOracleDao.java (UserInfoDao 인터페이스를 구현한 Oracle 버전 dao)

package ch13.domain.userinfo.dao.oracle;

import ch13.domain.userinfo.UserInfo;
import ch13.domain.userinfo.dao.UserInfoDao;

public class UserInfoOracleDao implements UserInfoDao {

	@Override
	public void insertUserInfo(UserInfo userInfo) {
		System.out.println("Insert into Oracle DB user ID= " + userInfo.getUserId());
	}

	@Override
	public void deleteUserInfo(UserInfo userInfo) {
		System.out.println("Delete from Oracle DB user ID= " + userInfo.getUserId());
	}

	@Override
	public void updateUserInfo(UserInfo userInfo) {
		System.out.println("Update into Oracle DB user ID= " + userInfo.getUserId());
	}
}

 

UserInfoClient.java (UserInfoDao 인터페이스를 활용하는 클라이언트 프로그램)

package ch13.web.userinfo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import ch13.domain.userinfo.UserInfo;
import ch13.domain.userinfo.dao.UserInfoDao;
import ch13.domain.userinfo.dao.mysql.UserInfoMySqlDao;
import ch13.domain.userinfo.dao.oracle.UserInfoOracleDao;

public class UserInfoClient {

	public static void main(String[] args) throws IOException {
		//인터페이스를 보고 사용한다.
		
		FileInputStream fis = new FileInputStream("db.properties"); //InputStream으로 db.properties파일 열기
		
		Properties prop = new Properties();
		prop.load(fis); //파일 읽어오기
		
		//두 개의 쌍으로 되어있는 값을 리턴해줌
		String dbType = prop.getProperty("DBTYPE"); //DBTYPE의 값 리턴 
		
		UserInfo userInfo = new UserInfo();
		userInfo.setUserId("12345");
		userInfo.setPassword("!@#$%");
		userInfo.setUserName("김혜린");
		
		UserInfoDao userInfoDao = null; //인터페이스 타입으로 변수 선언, 인터페이스니까 값이 null
		
		if( dbType.equals("ORACLE")) { //dbType이 어떤 값이냐에 따라 
			userInfoDao=new UserInfoOracleDao(); //null에 값을 넣어줌
		}
		
		else if (dbType.equals("MYSQL")) {
			userInfoDao=new UserInfoMySqlDao();
		}
		else {
			System.out.println("db error");
			return;
		}
		
		userInfoDao.insertUserInfo(userInfo);
		userInfoDao.updateUserInfo(userInfo);
		userInfoDao.deleteUserInfo(userInfo);
	}
}

 

 

 

3. 결론

db.properties 환경파일

 

1. db.properties 환경파일이 MYSQL 일때

DBTYPE=MYSQL

 

2. db.properties 환경파일이 ORACLE 일때

이렇듯 키값이 달라질 때마다 다른 구현이 나오는것, 이것이 결국 다형성인 것이다.

 

 

 

또다른 DB가 추가되어야겠으면, dao에 다른 DB 패키지를 만들고, UserInfo다른DB.java를 만든다. 

그리고 UserInfoClient.java로 와서 if문에 어느 클래스를 바인딩 시킬 건지 추가해주면 된다.

 

바뀌어야하는 구현 코드만 바뀌면 언제든지 replace 가능!

그렇지 않으면 통째로 소스코드를 관리해야 해서 유지보수가 어렵다는 단점이 있다.

 

인터페이스를 선언하고,

다양한 인터페이스를 다양한 정체로 구현할 수 있게끔 구현하면 다양하게 replace 가능하다. 

우리 코드에서는 키값에 따라 다른 버전의 DB가 돌아가게끔 구현했다.

profile

Burninghering's Blog

@개발자 김혜린

안녕하세요! 반갑습니다.