데보션 영 조별 활동 미션 중 하나가 IT 분야 책 1권을 같이 읽고 나누는 활동이다.
우리 조 데브리버가 선정한 책은 바로 ' 쉽게 배워서 바로 써먹는 디자인 패턴 ' 이다.
이 책에서 다루는 24가지의 패턴은 공통적으로 이름, 문제, 해법, 결과라는 요소를 가진다.
책이 두껍고 패턴의 종류도 많아서 조원들과 나눠서 함께 읽어보았다.
내가 맡아 읽은 부분은 행동 패턴 뒷부분.
책에서 다룬 행동 패턴은 반복자 패턴, 명령 패턴, 방문자 패턴, 체인 패턴, 감시자 패턴, 중재자 패턴, 상태 패턴, 메멘토 패턴, 템플릿 메서드 패턴, 전략 패턴, 인터프린터 패턴이 있다.
그 중 상태 패턴과 메멘토 패턴을 살펴보고자 한다.
상태 패턴은 조건에 따른 별개의 동작을 객체를 캡슐화하여 독립된 동작으로 구분하는 패턴이다. 때문에 상태 패턴은 상태 표현 객체라고도 불린다.
상태값은 처리 로직을 구별할 수 있는 특정한 값으로 조건 비교, if문을 사용하여 동작을 분리한다.
모든 상태에 대해 객체를 생성하고 관리하는데, 새로운 상태 객체를 생성하는 것은 시스템의 메모리 자원을 할당하는 일이다.
<?php
const OPEN = 0x01; //주문
const PAY = 0x02; //결제중
const ORDERED 0x04; //주문완료
$state = NULL;
$state = OPEN;
if ($state == OPEN) {
echo “주문\n”;
} else if ($state == PAY) {
echo “결제중\n”;
} else if ($state == ORDERED) {
echo “주문완료\n”;
}
여기서 if문을 switch문으로 바꾸면 더 효율적이고 높은 성능을 발휘할 수 있다.
그런데 제어문은 규모가 커질수록 코드의 흐름을 이해하고 전체 동작을 파악하는데 많은 시간이 필요하다는 단점이 있다. 이럴 때 가변함수를 이용하면 보다 명확히 구분할 수 있다.
<?php
$state = “ordered”;
if($state && function_exists($state)){
$state();
}
// 오픈상태
function open()
{
echo “주문\n”;
}
//결제상태
function pay()
{
echo “결제중\n”;
}
//주문상태
function ordered()
{
echo “주문완료\n”;
}
//완료상태
function finish()
{
echo “처리완료\n”;
}
객체 형태로 상태를 분리할 경우 상태의 동작에 객체를 위임할 수 있다. 때문에 객체의 상태값과 직접적인 객체의 상태값에 영향을 받는다.
각 상태의 동작은 서브 클래스 형태로 캡슐화할 때 코드가 독립적으로 수행할 수 있도록 해야 한다. 이렇게 하면 각 클래스는 상태의 변화에 대응하며 독립적으로 실행 가능하다.
서브 클래스 생성시 인터페이스를 적용하는데, 이 인터페이스는 서브 클래스의 통일성을 유지하기 위해 사용한다.
한편, 각각의 상태를 객체로 캡슐화하다보면 클래스 파일이 늘어난다는 단점이 있다.
<?php
Class JinyOrder
{
private $state;
public function_construct()
{
$this->state = [
‘ORDER’ => new StateOrder(),
‘PAY’ => new StatePay(),
‘ORDERED’ => new StateOrdered(),
‘FINISH’ => new StateFinish()
];
}
public function process($status)
{
$this -> state[$status]->process();
}
}
초기화 과정에서 상태별로 클래스의 객체를 생성하는데 각 상태에 따라 여러 변수를 추가로 사용하는 것이 단점이라고 할 수 있다.
상태 패턴은 상태값에 따라 실제 동작되는 상태 객체를 결정하고 호출하는데 상태 전이를 통해 관리할 수 있다. 상태 전이(state transition)은 동작에 따라 변하는 상태값으로 특정한 규칙에 의해 변동되며, 상태 패턴이 바로 이 상태 전이를 명확히 표현한다.
상태 전환은 코드의 흐름에 따라 상태를 처리하며 현재 자신의 상태를 유지하는 것으로 상태를 공유할 때 정적 변수를 응용하여 표현할 수 있다.
상태패턴의 효과
- 조건문 해결 : 조건 분기 없이 상태값을 이용용
- 런타임 : 상태별로 위임 객체를 변경
- 확장성 : 동작을 상태 객체에 위임하여 확장
- 변화 : 변경된 상태에 따라 행동을 위임임
메멘토 패턴은 객체의 상태를 저장하여 이전 상태로 복구하는 패턴으로 SolverState로 객체의 상태를 관리한다. 객체의 상태를 저장하고, 저장된 상태의 객체를 복원한다.
객체가 동작 전의 상태로 만드는 방법은 2가지로, 객체를 실행하기 전에 동작을 역순으로 처리하는 로직을 다시 작성하는 방법과 객체의 동작을 되돌리기 위해 실행 전의 객체를 통째로 저장하는 방법이다. 두번째 방법이 첫번째 방법에 비해 수월한 편이이다.
메멘토 패턴은 캡슐화를 파괴하지 않고 객체 상태를 저장하고, 객체 저장은 스택 구조 배열을 사용한다.
객체 저장과 복원 위한 인터페이스
- 원조본(originator)
- 케어테이커(caretaker)
구현 방법
클래스 생성
<?php
class Memento
{
//객체를 저장
protected $obj;
//원조본(Originator)에 의해 생성
Public function _construct($obj)
{
//객체를 복제
$this->obj = clone $obj;
}
//저장된 객체 읽기
public function getObject()
{
return $this->obj;
}
}
- 클래스를 protected 속성 사용하여 저장
- 상속 클래스 내부에 매서드 생성
- 객체를 저장, 복원을 위한 Originator 클래스 생성
<?php
Class Originator
{
protected $state;
public function create()
{
echo “>메멘토 객체를 생성합니다. \n”;
return new Memento($this->state);
}
public function restore($memento)
{
echo “>메멘토 객체로 복원합니다.\n”;
$this->state = clone $memento->getObject();
}
public function getState()
{
return $this->state;
}
public function getState()
{
return $this->state;
}
public function setState($state)
{
$this->state = $state;
}
}
*Originator 클래스는 객체를 복원 또는 저장하기 위한 프로피터 하나 가지고 있음.
케어테이커(caretaker)는 실행 취소 메커니즘이고, 제한적 범위의 인터페이스를 가집니다. 또한, 다수의 메멘토를 보관하고, 관리한다.
<?php
class CareTaker
{
protected $stack;
public function _construct()
{
$this->stack = array();
}
public function push($origin)
{
$memento-> $origin->create();
array_push($this->stack, $memento);
}
public function undo($origin)
{
$memento = array_pop($this->stack);
$origin->restore($memento);
return $origin->getState();
}
}
또한, CareTaker클래스는 메멘토 객체를 스택 구조로 저장하며 복원시 스택에서 메멘토를 가져온다.
메멘토 패턴과 같이 활용하는 패턴
- 명령 패턴
- 프로토타입 패턴
- 상태 패턴
- 반복자 패턴
이 책을 읽으면서 객체지향 개발에서 사용되는 다양한 디자인 패턴을 알게 되었다. 같은 책을 함께 읽고 나누면서 어려운 내용을 쉽게까지는 아니지만 조금은 이해하는 쪽으로 갈 수 있었다. 서로 이해한 내용을 설명하다보니 그게 잘 안되는 부분도 있었고, 실제 내용도 어렵기도 하고. 그래도 다음 회독 때는 첫 회독보다는 낫겠지 싶을 듯하다.
객체 지향 개발에 관심만 있었지, 패턴은 어렵게만 느껴졌었다. 패턴을 기억해두었다가 필요할 때 사전처럼 다시 펴서 해당 부부을 살펴봐야겠다.
'Activities > SKT DEVOCEAN YOUNG 1기' 카테고리의 다른 글
DEVOCEAN YOUNG 3기 모집(~1/31) (0) | 2024.01.25 |
---|---|
(마감임박)~2/23 대학생 테크인플루언서 DEVOCEAN YOUNG 2기 모집 (0) | 2023.02.21 |
2022 SK TECH SUMMIT 참가 후기 (0) | 2022.11.17 |
2022 SK TECH SUMMIT 개최 (오프라인 등록 ~11/6 24:00) (0) | 2022.10.26 |
[online] 데보션 전문가를 만나다 후기 (0) | 2022.10.11 |
댓글