Subscription Form
Contributors

* 디자인 패턴 적용시 중요한 세가지 규칙

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

출처.mystery log

 

Total
0
Shares

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다