Null Object Pattern

널 오브젝트 패턴을 정리한다.

기존의 not null check

1
2
3
4
Employee e = DB.getEmployee("Bob");
if (e != null && e.isTimeToPay(today)) {
e.pay();
}

not null 확인은 관용적인 표현이지만 보기 싫고, 에러가 발생하기 쉽다.
DB.getEmployee 가 null 대신 예외를 발생시키면 에러가 발생할 위험을 감소시킬 수 있다.
하지만, try/catch 블록이 추가되어야한다.

Null Object Pattern 적용

널 오브젝트 패턴을 사용하면 null 검사 코드가 제거되고 코드를 단순화시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class DB {
public static Employee getEmployee(String name) {
return Employee.NULL;
}
}

public interface Employee {
public boolean isTimeToPay(Date payDae);

public void pay();

public static final Employee NULL = new Employee() {

public boolean isTimeToPay(Date payDae) {
return false;
}

public void pay() {

}
}
}

Employee e = DB.getEmployee("Bob");
if (e.isTimeToPay(today)) {
e.pay();
}

없는 직원을 익명 내부 클래스로 만들어서, 인스턴스가 오직 하나임을 보장한다.
없는 직원 내부에서는, isTimeToPay 는 false 를 반환하고 아무 임금도 지급하지 않는다.


클린 소프트웨어 <로버트 C.마틴>

Read more

Singleton && MonoState Pattern

싱글톤 패턴과 모노스테이트 패턴을 정리한다.

Singleton Pattern

단 하나의 인스턴스를 가져야하는 클래스가 있을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton {
private static Singleton theInstance = null;

private Singleton() {

}

public static Singleton Instance() {
if (theInstance == null) {
theInstance = new Singleton();
}

return theInstance;
}
}

Monostate Pattern

단일성을 이루기 위한 또 다른 방법이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Monostate {
private static int itsX = 0;

public Monostate() {

}

public void setX(int x) {
itsX = x;
}

public int getX() {
return itsX;
}
}

public class Test {

public void testInstanceBehavesAsOne() {
Monostate m1 = new Monostate();
Monostate m2 = new Monostate();

for (int x = 0; x < 10; x++) {
m1.setX(x);
assetEquals(x, m2.getX());
}
}
}

싱글톤 패턴은 단일성 구조를 강제하여 둘 이상의 인스턴스가 생성되는 것을 막는다.
모노스테이트 패턴은 구조적인 제약은 없지만, 단일성이 있는 행위를 강제한다.


클린 소프트웨어 <로버트 C.마틴>

Read more

Facade && Mediator Pattern

퍼사드 패턴과 미디에이터 패턴을 정리한다.

Facade Pattern

복잡하고 일반적인 인터페이스를 가진 객체 그룹에 간단하고 구체적인 인터페이스를 제공할 때 사용된다.

DB 클래스가 Application 이 java.sql 의 구체적인 내용을 알 필요가 없게 보호하고 있다.
즉, java.sql 의 일반성과 복잡성을 간단하고 구체적인 인터페이스 뒤에 숨긴다.

퍼사드 패턴의 사용은 개발자가 모든 DB 호출이 DB 클래스를 통과해야한다 라는 규정을 의미힌다.
Application 코드의 어떤 부분이 직접 java.sql 을 사용한다면 규정을 위반하는 것이다.
이 처럼, 퍼사드는 자신의 정책을 Application 에 적용하고 있다.

Mediator Pattern

미디에이터 패턴도 정책을 적용한다.
퍼사드가 자신의 정책을 가시적이고 강제적인 방식으로 적용했다면, 미디에이터 패턴은 자신의 정책을 은밀하고 강제적이지 않은 방식으로 적용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class QuickEntryMediator {

private JTextField itsTextField;
private JList itsList;

public QuickEntryMediator(JTextField t, JList l){
itsTextField = t;
itsList = l;

itsTextField.getDocument().addDocumentListerner(new DocumentListener() {
public void changeUpdate(DocumentEvent e){
textFieldChanged();
}
})
// ...
}

private void textFieldChanged() {
// ...
}
}

QuickEntryMediator 는 익명 DocumentListener 를 JTextField 에 등록한다.
이 리스너는 텍스트에 변화가 있을 때마다, textFieldChanged 를 호출한다.

Read more

Template Method && Strategy Pattern

템플릿 메서드 패턴과 스트레티지 패턴을 정리한다.

Template Method Pattern

버블 정렬을 예로 들어보쟈.

1
2
3
4
5
6
7
8
9
10
11
public abstract class BubbleSorter {

protected int doSort() {
// ...
if(outOfOrder(index)) swap(index);
// ...
}

protected abstract void swap(int index);
protected abstract boolean outOfOrder(int index);
}

BubbleSorter 로 다른 어떤 종류의 객체든 정렬할 수 있는 간단한 파생 클래스를 만들 수 있다.
ex) IntBubbleSorter, DoubleBubbleSorter …

템플릿 메서드 패턴은 고전적인 재사용 형태의 하나이다.
일반적인 알고리즘은 기반 클래스에 있고, 다른 구체적인 내용에서 상속된다.
하지만, 상속은 아주 강한 관계여서 파생 클래스에서 필연적으로 기반 클래스에 묶이게 된다.

Strategy Pattern

버블정렬에 적용해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public abstract class BubbleSorter {

private SortHandle sortHandle = null;

public BubbleSorter(SortHandle handle){
sortHandle = handle;
}

public int sort(Object array){
// ...
if (sortHandle.outOfOrder(index)) sortHandle.swap(index)
// ...
}
}

public interface SortHandle {
public void swap(int index);
public boolean outOfOrder(int index);
public int length();
public void setArray(Object array);
}

public class IntSortHandle implements SortHandle {
private int[] array = null;

// ...
}

IntSortHandle 의 swap 과 outOfOrder 메서드는 버블 정렬 알고리즘에 직접 의존하고 있지 않다.
그래서, BubbleSorter 가 아니라 다른 Sorter 의 구현과도 사용할 수 있다.

Read more

Command Pattern && Active Object Pattern

커멘드 패턴과 액티비 오브젝트 패턴을 정리한다.

Command Pattern

1
2
3
4
public interface Command
{
public void do();
}

대부분의 클래스는 한 벌의 메서드와 변수의 집합을 결합시키는데, 커멘드 패턴은 그렇지 않다.
오히려 함수를 캡슐화해서 변수에서 해방시킨다. 즉, 함수의 역할을 클래스 수준으로 격상시킨다.

AddEmployeeTransaction

직원들의 DB 를 관리하는 시스템을 작성하는 예를 보자.
command 객체는 검증되지 않은 데이터를 위한 저장소 역할을 하고, 검증 메서드를 구현하고 마지막으로 트랜잭션을 실행하는 메서드를 구현한다.

예를 들어, AddEmployeeTransaction 은 Employee 가 포함하는 데이터를 모두 가지고 있다.
validate 메서드는 모든 데이터를 살펴보고 문법적으로나 의미적으로 오류가 없는지 확인한다.
또한, 트랜잭션의 데이터가 기존의 데이터베이스 상태와 일치하는지 확인할 수도 있다.
execute 메서드는 검증된 데이터를 사용해 데이터베이스를 갱신한다.

물리적, 시간적 분리

이 방식의 장점은, 사용자에게 데이터를 받는 코드와 데이터 검증 및 작업 코드를 분리할 수 있다는 것이다.
검증과 실행 코드를 따로 떼어 AddEmployeeTransaction 클래스에 넣으면, 이 코드를 입력 인터페이스에서 물리적으로 분리한 것이 된다.

Read more