본문 바로가기

Program/Design Pattern

[Design Pattern] Factory Pattern(팩토리 패턴 : 추상 팩토리 패턴)

 디자인 패턴 중 Factory Pattern은 다른 디자인 패턴들보다 확장성에 더 중점을 가진 패턴이라고 해도 과언이 아닐 것이다.

공장에서 물건을 생산할 때 생산라인의 생산공정을 교체하여 각기 다른 제품들을 생산하는 것과 비슷한 원리라고 생각하면 된다. 특히 추상 팩토리 패턴에서는 이런 식으로 원하는 상호간의 의존성을 줄이면서도 클래스를 확장시키면서 매우 효율적인 확장성을 가질 수 있게 된다.

 

 하지만 팩토리 패턴에도 단점이 없는 것이 아니다. 이는 팩토리 패턴의 특성상 당연한 일이다. 예를 들어 3개 제품을 생산하는 공장에서 생산과정 중 하나가 수정이 되었다고 가정해 보자. 제품이 3개뿐이 안되기 때문에 3개의 제품에 대하여 생산과정을 하나씩 수정하는 것은 그리 어려운 일이 아닐 것이다. 하지만... 생산하는 제품이 100개, 아니 1000개 혹은 그 이상이라면?? 어쩌면 최악의 상황이 나올 수도 있을 정도로 유지보수에 엄청난 시간이 들어갈 수도 있는 것이 팩토리 패턴이다. 

 

 하는 일이 자바가 아닌지라... 그래도 심심풀이로 만든 소스가 만들고 보니 추상 팩토리 패턴이기에;;

 샘플용이라고 하기엔 좀 복잡할 수도 있고, 더 좋은 방법이 있을 수도 있지만... 이 글의 목적이 어떤 구조의 소스가 더 좋다, 나쁘다 구분하는 것이 아닌 '이런 방법도 있지만, 난 이렇고, 저렇게 생각하고 그게 이런 면에서는 더 좋을 수 있을 것 같다' 라는 생각의 교환 및 공유의 자리가 되었으면 좋겠다.

 

 일단 예제 소스는 데이터베이스 회사 종류에 따라 데이터베이스를 사용하게 하는 소스이다. 예를 들어 어떤 프로그램이 하나 있는데 이 프로그램을 사용하는 업체들은 데이터베이스 종류가 다르다고 할 경우 업체마다 어떻게 적용시킬 것인가를 고민한다면, 이런 방법도 하나의 대안이 될 수 있을 것이다.

 

 본래 이 소스의 목적은 위에서처럼 업체들마다 데이터베이스가 다르기 때문에 사용자의 환경에 맞게 사용할 수 있게 변경이 필요한 Query클래스, 각 데이터베이스의 환경설정이 되어있는 properties 파일만 공개시키고 나머지는 그냥 알아서 돌아가게 하도록 하여 다른 소스 코드를 최대한 숨겨 보자는 것이였다. 물론 ibatis, mybatis 등을 사용해야 하지만 귀찮아서 생략..

 

먼저 uml을 보면...

 

 

TestMain : 프로그램 본체

TestDBControl : 데이터베이스 설정을 교환 역할인 클래스

TestDBKindMap : 데이터베이스 종류에 따른 클래스 위치가 저장되어있는 클래스

iTestDBQuery : Query 인터페이스

iTestDBConnector : 데이터베이스 Connection 생성 인터페이스

 

구조를 설명하면...

1. TestMain 클래스는 프로그램의 본체. 프로그램이 어떤 DB를 사용하는지 모른다. 그저 TestDbControl 클래스가 넘겨주는 iTestDBQuery 인스턴스를 받아서 사용할 뿐이다.

 

2. TestDbControl 클래스는 설정되어있는 데이터베이스에 맞게 Connection을 생성한 뒤 Query 클래스에 담아 TestMain 클래스에 인스턴스를 넘겨준다.

 

3. 인터페이스를 이용하여 의존 관계를 최소화 하여, 이후에 쿼리문 뿐만 아니라 데이터베이스가 바뀌거나 새로 추가 된다 하더라도 하위의 데이터베이스 관련 클래스 또는 파일만 수정, 추가하면 됨.

 

 

 

 

 

* TestMain.java

 

* TestDBComtrol.java : TestDBKindMap에서 정해진 데이터베이스 관련  클래스들의 객체를 생성하여 데이터베이스 connection을 담은 Query클래스의 인스턴스를 받아와서 TestMain으로 전달.

 

 

* TestDBKindMap.java

 

* iTestDBConnector.java

 

*iTestDBQuery.java

 

* TextOracleConnector.java

 

* oracleJDBC.properties

oracleJDBC.dbname=oracleoracleJDBC.url=jdbc:oracle:thin:@localhost:1521:orcloracleJDBC.username=****oracleJDBC.password=****

 

* TestOracleQuery.java

 

*TestPostgreSqlConnector.java

 

* postgresqlJDBC.properties

postgresqlJDBC.dbname=postgresqlpostgresqlJDBC.driverClass=org.postgresql.DriverpostgresqlJDBC.url=$jdbc:postgresql://localhost:5432/TestDBpostgresqlJDBC.username=****postgresqlJDBC.password=****

 

 

* TestPostgreSqlQuery.java

 

데이터베이스의 데이터는 간단히 입력해 놓고... 결과

 

 

 TestDBComtrol클래스에서 데이터베이스를 oracle로 셋팅하고 돌려도 잘 동작한다.

 

 클래스 간의 의존관계를 약하게 하여 데이터베이스가 바뀌거나 쿼리가 바뀌어도 본체인 Main 클래스는 본체답게 그냥 프로그램의 중심을 지키는 것이 핵심. 이렇게만 보면 인터페이스를 이용하여 클래스 사이의 의존관계를 약하게 하는 것이 추상 팩토리 패턴의 핵심이라고 할 수도 있겠다. 물론 상속관계라면 또 달라지겠지만...

 

 디자인 패턴이라는 것이 어려우면서도 사실은 별것이 아니다. 어떻게 보면 '인터페이스를 이용해서 의존관계를 약하게 한 다음 인스턴스를 불러와서 사용하고 쉽게 확장할 수 있도록 하자'를 '팩토리 패턴을 사용하자. 음.. 추상 팩토리 패턴이 좋겠군'라고 그냥 부르기 쉽게 하려고 만든 것일지도 모른다는 생각이 들을 정도로;; 분명 이런 용도도 있을 것이다.

'Program > Design Pattern' 카테고리의 다른 글

[Design Pattern] 디자인 패턴?  (0) 2011.07.05