Site Search :
Standard Enterprise XML Methodology Pattern Setting Tunning Other
Article Contributors
GuestBook
Javapattern Maven
XSourceGen Dev
JetSpeed Test
JLook Image
jLook Family Site


기본패턴 Overview part-1
 
기본적인 패턴에 대한 간략한 개요를 보도록 한다. ( 2003/03/07 ) 788
Written by ienvyou - 최지웅
1 of 1
 

▶ 디자인 패턴 적용시 중요한 세가지 규칙
1. Implementation class 가 아닌 interface 를 이용
2. Inheritance 가 아닌 Delegation 을 사용

    public interface AA {
        public String getInfo();
    }
    public class Super implements AA {
        public String getInfo() {}
    }
    public class Sub {
        AA delegator;
        public void test() {
             delegator.getInfo();
        }
    }

cf ) white-box reuse : Inheritance	vs. black-box reuse : Delegation

3. Coupling 의 최소화
* 커플링 : 어느 하나의 기능 변화가 전체 시스템의 구조에 영향을 미치는 정도
> 이것이 커질수록 잘못된 디자인

>> Refactoring 과 design pattern
    > 실제 문제 분석이 종료된 이후 좀더 효율적인 코드로 변화시키는 것을 refactoring 이라 한다.
    > 이 과정에서 디자인패턴이 적용되어지는 경우가 많다
    > 구현하기 이전에 보지 못했던 디자인상의 문제점들을 실제 구현에 들어가 이를 개선하는 것

>> Anti-Pattern
> s/w 를 만드는 과정에서 쉽게 도출되는 바람직하지 않은 방법들

> 종류
    - 관리상의 안티
    - architecture 상의 안티
    - 개발상의 안티
> 대표적인 anti-pattern
    - Spaghetti code : 개발과정에서 나타남.  기능의 추가로 인해 코드의 복잡도가 증가, 꼬이는 현상
    - Stovepipe System : architecture의 문제, 확실한 추상화가 없이 하나로 묶어 제품을 만드는 경우
    신뢰성, 유지보수가 모두 저하
    - Analysis Paralysis : 분석단계에서 너무 완벽함을 추구하다보면 개발 진행 자체가 마비
    - Swiss Army Knife :  architecture 작성시 하나의 객체에 너무 많은 기능/인터페이스를 넣는 경우 복잡, 
    유지보수 난이, 커플링 증가
    - Ambiguous Viewpoint : 불명확한 상태에서 모델링을 진행 -> 객체의 불명확



1) Facade pattern
    > 여러 객체들이 가지는 logic 을 하나의 객체로 집중시키는 형태
    > helper, wrapper라고도 한다
    > client side에서 접근해야 할 클래스가 많은 경우 앞단에 Facade class를 만들어 이를 통해 접근
    > client 와 내부 구현 class 와의 coupling 최소화
    > logic 에서 jdbc api에 의존적이지 않음으로 인해 sqlj , oodb 등의 지원을 독립적으로 수행 가능.
    > java.net.URL class 가 대표적인 예

    public interface JDBCHelper {	}
    public class JDBCStatementHelper implements JDBCHelper{  }
    public class JDBCPrepStatementHelper implements JDBCHelper{  }


2) Factory method pattern 
    > logic 측의 요청에 따라 서로 다른 객체를 생성하는 Factory 를 정의
    > 하나의 facade class 내의 계속적인 기능추가는 로직의 복잡성과 runtime error 유발 가능성 고조
    > factory pattern 의 사용시 기능 확장 및 추가에 따라 facade interface 를 상속/구현한 클래스들의 
    추가 가능해짐
    > 또한 하단에서 상속받은 메소드의 사용하지 않음을 별개로 결정가능
        ex) Statement 의 경우 setType() 을 비롯한 메소드들의 사용 금지

    public class JDBCHelperFactory { 
     JDBCHelper createJDBCHelper(){}
    }

    JDBCHelper helper = factory.createJDBCHelper( ip, port, sid, 
        JDBCHelperFactoryIF.HELPER_STATEMENT );
    JDBCHelper helper1 = factory.createJDBCHelper( ip, port, sid, 
        JDBCHelperFactoryIF.HELPER_PREPARED_STATEMENT );


3) Strategy pattern 
    > client 의 다양한 action 처리를 필요로 하는 경우
    > 복잡한 switch 문 을 하나의 클래스로 독립 -> 보다 readability 가 증가한다.
    > 처음 application 수행시 종류가 결정됨

    - os , db별로 서로 다른 처리를 하려 할때
        -> 한글 converting 작업을 수행하는 별개의 클래스 도입
        -> 이를 JDBCHelper 즉 facade 에서 보유
        -> 코드변환시 적절히 호출
        -> 기능 추가, 변경이 용이해짐.
	
5) Cache Management Pattern
	cf) Cache
		> 작은 용량의 빠른 기억장치를 사용, 대용량의 느린 기억장치의 access 속도 개선
		> 데이타베이스의 경우 data 들의 일부를 server상에 memory cache 기법을 사용 일부 
        보관하는 방법을 말한다
		

    > Cache 의 구현시 필요한 기능
        1) memory repository 구현
        2) repository management 기능 구현
        3) Kick-off 의 구현 : 저장소 size 초과시 하나의 객체를 저장소에서 다시 제거

    > class 구성
        -> Object Key
        -> CacheManager
        -> ObjectCreator
        -> Cache

6) Producer-Consumer pattern
    - Event 의 발생 을 EventQueue 에 저장
    - 이를 각 Event Consumer 에게 전달하고 이 Event object를 ActionManager 가 받아서 수행한다
    - 단일 Producer, Consumer 구조가 아님.

    > class 구성
        -> Producer
        -> EventQueue
        -> EventListener
        -> Consumer
        -> ActionManager
	
    > java api 에서 구현 예
        -> java.io.PipedInputStream, PipedOutputStream 
        -> Produer : PipedOutputStream
            -> PipedInputStream 을 내장
            -> write() 를 이용해 Queue에 데이타 produce
            -> 이때 queue 의 역할인 PipedInputStream.receive() 를 호출한다
        -> Queue + Consumer : PipedInputStream
            -> read() 를 이용해 queue에 저장되어 있는 데이타를 읽어낸다
            -> 이때 blocked i/o 이므로 데이타가 없을 경우 계속 대기한다
            -> 이를 해결하기 위해서 size(), available() 등의 메소드를 구현할 것



7) Dynamic Connection Pattern (동적연결패턴)
    - 초기화 시에 처리할 각 동작객체들을 해시테이블에 key , value 의 형태로 저장
    - 처리해야 할 시점에서 해시테이블로부터 처리객체를 얻어낸다
    - 처리객체는 abstract class 를 상속받아 만들고 실제 처리하는 쪽(클라이언트)에서는  
    abstract class 내의 method를 통해 각 처리객체들을 공통적으로 수행시킨다
    - 서버의 확장성 구체화
        -> 기능 추가시 flexible
        -> action은 preprocess, do, postprocess 로 나누어 처리하는 편이 좋다

    > 구성
        -> ActionAbstract class
        -> ActionImpl class...
        -> ActionManager : Hashtable 보유

8) Command pattern
    - client/server 간에 수행해야 할 작업을 전달할때 command 를 별도로 정의하고 이를 처리할 
    command처리기를 디자인
	
    > 구성
        -> AbstractCommand
        -> ConcreteCommand class
        -> CommandManager

9) Guarded Suspension pattern
    - 실제 실행하는 부분의 처리 프로세스의 갯수를 제한
    - 어떤 전제조건이 만족되기 전까지는 수행을 계속하고 벗어나는 경우는 계속 대기하는 형태
    - 주의사항 ; 적절한 notify 가 없을 경우는 deadlock 이 발생할 수 있다

    > 구성
        -> CommandQueue
            -> singleton pattern
            -> 처리될  command 객체들을 담을 Queue 를 가짐
            -> queue 에서 data 를 꺼내고 넣는 동작 구현 (push,pop)
            -> 이때  범위를 지정하고 제어한다

10) Immutable pattern
    - 한번 만들어진 객체는 변화시키지 않는다
    - 변화가 발생할 때는 새로운 객체를 생성해서 적용시킨다
    - 대표적인 예 : java.lang.String

11) Adapter pattern
    - interface + adapter + implementation class 
    - 여러 객체들이 하나의 interface에 의해 사용되어진다
    - client에게는 interface만 노출되며 이의 호출이 adapter에게 전달된다
    - adapter는 내부적인 수행 로직을 갖지는 않으며 로직을 갖고 있는 또다른 클래스인 
    adapter를 호출 이를 처리한다

    - adapter의 role : client의 interface에 의한 호출을 실제 구현객체에게 전달하는 형태
    - adapter와 adaptee 의 관계는 use 
    - 대표적인 예 : java.awt.event 내의 XXXAdapter class  

12) Bridge pattern
    - 여러개의 추상클래스들을 서로 관계를 주어 정의하고 이를 구현한 클래스들 역시 동일한 
    관계를 가지는 형태
    - AbstractA + AbstractB + AImpl + BImpl
    - AbstractA 와 AbstractB는 상속관계
    - AImpl 은 AbstractA를 BImpl은 AbstractB를 구현(use)한 객체
    - AImpl 과 AbstractB와의 관계 역시 구현(use) 관계

    - 대표적인 예 : java.awt.Component 와 java.awt.peer.ComponentPeer, Button과 ButtonPeer
        -> ComponentPeer interface 
            -> Button 같은 Component의 하위 클래스들이 구현될 때 요구되는 상호 운용 환경에 
            의존적인 method들 정의
        -> ButtonPear interface
            -> Button 에서 구현해서 사용
        -> Component와 ComponentPeer 의 관계가 Button class와 ButtonPeer interface간에 동일하게 유지됨
	
13) FlyWeight Pattern
    - 동일한 정보를 가지는 객체들의 재활용 : pooling
    - 재사용성 증대
    - AbstractA + ImplA1 + ImplA2 + FactoryA
    - client가 ImplA1 객체의 요청을 Factory 에게 전달
    - Factory는 자신의 pool내에 동일한 정보를 가지는 객체가 있는지 체크
    - 없을 경우 새로 생성, 이를 pool에 넣고 서비스

    - 대표적인 예 : java.lang.String - string literal 은 재사용된다.  별개의 풀링 : 이를 수행하는 
    메소드 String.intern() 임
        -> 매번 String  listeral 을 생성하라는 요청이 들어오면 intern()이 호출됨
        -> 풀링을 체크, 서비스하는 기능이 native method로 구현되어 있슴

        -> 워드프로세서에서 문자 객체
        -> HTML 의 구문처리를 위한 Element 객체 등

    - immutable pattern 과 아울러서 사용되는 경우가 많다.

14) Template Pattern
    - 공통적인 행위를 하는 여러 클래스들의 집합을 정의한 패턴
    - abstract class를 정의하고 내부에 공통 행위를 abstract method로 기술한다
    - 여기까지는 상속의 개념과 동일하다
    - 또한 abstract class내에는 정의된 abstract method를 이용해 처리하는 로직 메소드를 담는다
        -> 이를 template mathod라고 한다
        -> template method내에는 business logic, algorithm 이 포함
        -> concrete class(sub class) 내에 구현되어 있을 abstract method를 호출함으로써 동작한다
    - 장점
        -> 코드 중복 방지
        -> 기능의 추가 및 변경이 쉽다
        -> 새로운 기능 추가시 concrete class 만 새로이 정의하면 ok

    - 사용 예 : java.io.*
        - InputStream , OutputStream class 
            -> public abstract int read() throws IOException 이 abstract method임
            -> template method
                -> read(byte[], int, int ) .... 여러 버젼의 메소드
                -> skip()
            -> 아랫단에 이를 상속받은 FileInputStream class에서 read( byte[], 10, 20 ) 을 사용
            -> SequenceInputStream, PipedInputStream 을 비롯한 몇가지 클래스 모두 동일한 구조

15) Proxy pattern

    * Remote proxy
        -> 다른 address space를 지닌 객체에 대한 로컬 대리자를 제공
        -> rmi, ejb에서 사용
        -> rmi 의 stub(client) / skeleton(server) 에 해당.


    * Counting proxy
        -> 분산환경에서 사용하는 경우 있다. 
        -> request 마다  reference count 증가 시키면서 관리 
        -> 이를 garbage collection 에서도 사용 가능.
        -> smart reference
            - reference 대치
            - ATL에서 smart reference의 경우 스스로에 대한 참조 카운트를 유지하다가 0이 되는 경우 
            자동으로 free

        cf) ATL (Active Template Library)

        C++ 또는 비주얼 C++를 이용하여 ASP 코드나 다른 액티브엑스 프로그램 컴포넌트를 만들 때 
        사용하는 마이크로소프트의 프로그램 라이브러리이다.  ATL은 ASP 페이지 상의 스크립트에서
        호출할 수 있는 COM 객체를 만들 수 있게 해준다. 마이크로소프트에 의하면, 이러한 객체들은 
        빠르고, 여러가지 강점을 가지고 있다고 한다. ATL을 이용하여 만들게되는 객체들은 모든 콘트롤,
        익스플로러 콘트롤, 프로퍼티 페이지 및 대화상자 등을 포함한다. 

        * Virtual proxy
            -> 실제 객체의 생성 비용이 높은 경우 virtual proxy를 먼저 생성
                -> 실제 객체 사용시점까지 실제 객체의 생성을 늦출 때 사용
            -> Remote object layer에서 사용. 
            -> Servant 생성시 비용 소요가 크다
                -> 이를 최대한(클라이언트가 직접 호출할때까지) 보류시키는 역할
            -> 만약 실제 bean 생성하는 시간이 너무 오래 걸리는 경우 이용.  
            -> lazy initializing 방식(예. MediaTracker class)
	
        cf)  ejb에서의 proxy : method interposing -> declarative Programming을 가능케 한다.
            deployee tool에 의해 객체가 생성되어지는 과정에서 아래와 같은 작업 추가 가능.
            1) security code 삽입 가능. : 특정 유저인 경우 roll을 dd에서 확인한 후 작업
            2) 분산 트랜잭션 관리 가능 : 트랜잭션과 관련이 있는 특정 메소드인 경우 DD로부터 확인하여
            코드 앞뒤에 begin, commit 처리를 추가할 수 있다.
	
        * Protection Proxy
            - 실제 객체에 대한 직접적인 접근을 제한하려 할때 앞단에 설치

		
		
16) Single Threaded Execution pattern
    - 단일 쓰레드의 접근만을 허용하는 패턴
    - 예 ) java.util.Hashtable, Vector

    - 이를 실제로 구현하기 위해서는 synchronized() , synchronized method를 이용한다.


17) Abstract Factory Pattern
    - client의 interface는 ConnectionFactory 이며 실제로 이를 구현한 다양한 
            ConnectionFactoryImpl class 정의
    - 실제 client에게 반환되는 객체는 FactoryImpl에 의해 생성된 ConnectionImpl 객체임

    - JDBC의 Connection, Connector architecture에 적용

    // 구성
    - ConnectionFactory : abstract factory
    - ConnectionFactoryImpl : factory
    - Connection  : abstract product
    - ConnectionA : product



2001-04-08
 
1
References
 
Copyright ⓒ 2003 www.javapattern.info & www.jlook.com, an jLOOK co.,LTD