디자인패턴

    (행동패턴) 비지터(방문자) 패턴

    비지터(방문자) 패턴 객체 그룹(콜렉션)에 대해 연산을 추가할 때, 연산을 그들이 작동하는 객체로부터 분리하는 패턴. 수행해야 하는 연산을 클래스에 정의하는 대신, 비지터라는 별도 클래스에 배치한다. 사용 시점 및 이유 객체 그룹(콜렉션)을 순회하면서 연산을 수행해야 할 때 그 연산이 메인이 아닌 보조연산으로 판단되어 클래스에서 떼어내고 싶을 때 혹은 클래스 계층 구조에서 일부 클래스에만 그 연산이 필요할 때 객체 구조(상속)는 거의 변하지 않지만, 전체 구조에 걸쳐 새로운 연산이 추가될 확률이 높을 때 구현 Element 구상 클래스에 따라 다른 구현 로직이 수행되어야 한다. 연산 클래스(visitor) 에서 한개의 메소드에서 instanceOf로 분기? -> visitor추가시 instanceOf 휴..

    (행동패턴) 템플릿메서드 패턴

    템플릿메서드 패턴 객체 연산에는 알고리즘의 뼈대만 정의하고, 구체적인 처리는 서브클래스에게 맡기는 패턴 validation체크와 같은 뼈대 로직은 템플릿메서드에 정의하고, 구체 로직은 서브클래스에 맡긴다. 사용시점 및 이유 어떤 알고리즘 중 변하지 않는 부분은 남겨두고, 변하는 부분만 서브클래스에서 정의하도록 남겨두고자 할 때 클래스들의 공통적인 행동을 추출하여 슈퍼클래스에 몰아둠으로써 코드 중복을 피하고 싶을 때 구현 추상 클래스에는 공통 로직인 templateMethod()가 있다. templateMethod() 내부에서 실제 구현인 method1()과 method2() 혹은 hook메서드를 실행한다. hook메서드는 기본적으로 슈퍼클래스에서는 아무것도 가지지 않은 메서드이고, 서브클래스에서 오버라이..

    (행동패턴) 전략 패턴

    전략패턴 알고리즘 군을 별도 클래스로 정의하여, 알고리즘을 상호 교환할 수 있도록 만드는 패턴 사용 시점 및 이유 하나의 클래스가 많은 로직을 갖고 그 로직이 여러개의 조건으로 인해 분기하여 복잡해질 때 내부 구현이 조금 다를뿐 개념적으론 관련된 클래스들이 존재할 때 사용자에게 알고리즘을 캡슐화 하고, 그 알고리즘을 다른 클래스에서도 재사용 하고 싶을 때 서브클래싱을 하지 않고 기능 확장을 하고 싶을 때 구현 Context는 사용자의 요청 을 전략객체로 전달하여 로직을 수행한다. Context의 정보를 Strategy에서 알아야 할 때가 있는데, Strategy 인터페이스에서 파라미터를 정교하게 설계하거나, Strategy 클래스들이 Context 클래스에 의존하도록 할 수도 있다. 두번째 방식은 Con..

    (행동패턴) 상태 패턴

    사용 시점 및 이유 현재 상태에 따라 다르게 행동하는 객체가 있을 때 상태에 따른 로직을 분기문을 이용하여 더러운 코드가 되었을 때 구현 클라이언트는 최초 Context생성시에만 초기화 상태를 지정해 주고, 그 이후 상태 흐름은 각 State오브젝트에 따른다. ConcreteState에서 doSomething()을 실행해주면, 그 내부에서 context의 다음 상태를 지정해 준다.

    (행동패턴) 옵저버 패턴

    사용 시점 및 이유 어떤 객체의 상태에 관심이 있는 오브젝트가 몇개인지 알 수 없을 때 관심이 있는 객체와 상태를 가진 객체간에 약결합 상태를 유지하고 싶을 때 구현 클라이언트는 Subject(주체) 객체에 addObserver 혹은 removeObserver를 통해 관찰하는(관심있는) 객체들을 추가 또는 제거 한다. subject에 상태가 변경시 notify()를 통해 가지고 있는 Observer들의 update를 실행해 준다. update 실행시 Push방식 혹은 Pull방식은 상황에 맞게 사용하여 구현한다. push: Observer에 통용할수 있는 파라미터로 인터페이스를 구성 후, Subject에서 알맞는 파라미터를 넘겨준다. pull: update 실행시 observer에서 subject로부터 ..

    (행동패턴) 메멘토 패턴

    사용시점 및 이유 undo기능이 필요하고, 객체의 내부 상태를 외부에 공개하고 싶지 않을 때 구현 Memento객체는 반드시 Originator를 통해 생성된다. Memento객체는 Originator객체의 상태를 저장하고 있고, 상태의 변경 또한 Originator를 통해 변경된다.(스냅샷 오브젝트 로써 역할) caretaker는 메멘토집합을 가지고 있다. caretaker는 메멘토 객체의 state를 바라보진 않고, 언제? 왜? 메멘토를 생성(원본데이터캡쳐) 하는지에 대한 로직을 구현한다.

    (행동패턴) 중재자 패턴

    사용 시점 및 이유 객체 조각들이 작고 많아졌을 때, 객체간 상호작용에 대한 구현을 하나의 객체로 모은다. 한 객체가 많은 다른 객체를 참조하고, 많은 의사소통을 하여 그 객체를 재사용 하기 힘들 때 기본 행동을 다른 로직들에서 조금의 차이로 인해 수많은 상속을 사용할 때 여러 객체가 복잡한 상호작용을 가져서 이해하기가 어려울 때 구현 클라이언트는 중재자 객체를 통해 기능을 실행할 수 있다. 중재자는 여러 실제 작동할 객체들의 레퍼런스를 가지고 필요한 로직을 수행한다. Colleague 오브젝트에게 연산이 발생하여 다른 Colleague에 상호작용이 필요할 경우, 직접 다른 Colleague에 알리지 않고 중재자에게만 알린다. 중재자는 그 변경을 자신이 가진 다른 Colleague들에게 알린다. (Col..

    (행동패턴) 이터레이터 패턴

    사용 시점 및 이유 콜렉션의 내부 구현 방식을 알 필요 없이 콜렉션 원소들에 접근하고 싶을 때 서로 다른 콜렉션 구조에 대해서 동일한 방식으로 순회하고 싶을 때 (순회 방법에 대해 추상화) 구현 구상 이터레이터의 생성은 콜렉션의 createIterator()로 생성한다. 클라이언트는 이터레이터 인터페이스를 통하기 때문에 콜렉션 및 이터레이터의 구체적인 구현에 대해서는 알 필요가 없다.

    (행동패턴) 커맨드 패턴

    사용 시점 및 이유 수행할 동작을 매게변수화 하고자 할 때 (callback을 객체지향화) undo(실행 취소) 기능을 구현하고 싶을 때. 실행할 연산들을 별도로 저장하여 장애 대응 시 편리하게 연산을 다시 실행하고 싶을 때 구현 Client는 Command와 Receiver를 이용하여 Invoker 를 생성한다. undo기능이 필요 할 경우 Invoker에서 실행한 커맨드들을 List로 가지고 있고(혹은 stack), command에서도 unExecute()를 구현한다. 장애시 연산 저장과 같은 기능을 원할 경우 Command 객체들을 직렬화 하여 별도로 저장해 둔다. Invoker는 자신이 어떤 Command 구상클래스를 가지고 어떤 명령을 실행하는지는 알 수 없다.

    (행동패턴) 책임연쇄패턴

    사용 시점 및 이유 요청을 처리할 객체들의 집합이 동적으로 정의 되어야 할 때 연결되어 있는 각 객체들에게 요청을 건내고, 그중 하나가 처리하면 될 때 (처리하고 종료하는 방식) 어느 객체의 핵심 로직에 대해서 부가기능들을 동적으로 추가하고 싶을 때 (계속해서 전달 하는 방식) 구현 각 책임을 가진 구상 객체들은 BaseHandler를 상속받아 구현한다. 구상 핸들러 객체는 자신이 실행할 수 있는 명령일 경우 실행하고 종료할 수도 있다. (처리 하고 종료) 구상 핸들러 객체는 자신의 기능을 실행하고 연결된 Next Handler를 실행하도록 할 수 있다(전달)