스프링이 사랑한 디자인 패턴
디자인 패턴은 객체 지향의 특성 중 상속(extends), 인터페이스(implements), 합성(객체를 속성으로 사용) 을 이용한다. 다른 방식은 없다.
extends), 인터페이스(implements), 합성(객체를 속성으로 사용) 을 이용한다. 다른 방식은 없다. 1. 어댑터 패턴(Adapter Pattern)
두 인터페이스가 공통된 규격이 없어 사용이 불가할 때(혹은 공통된 규격을 사용하고 싶을 때), 어댑터는 변환기로 공통된 규격을 통해 통신할 수 있도록 한다.
인터페이스 상속(
implements) 을 통해서 구현예시
다양한 데이터베이스 시스템을 공통의 인터페이스인 JDBC 를 통해 조작한다.
자바에서는다양한 운영체제의 기계어를 JVM 을 통해서 만들어낸다.
한문장으로 정리하면 다음과 같다. "인터페이스가 맞지 않는 두 객체 간의 협력을 가능하게 만드는패턴"
어댑터 패턴이 적용되지 않은 코드
main()메서드를 살펴보면 sa, sb 를 통해 호출되는 메서드가 비슷한 일을 하지만, 다른 메서드 명을 사용하고 있는 것을 볼 수 있다.
public class ServiceA {
void runServiceA() {
System.out.println("ServiceA");
}
}
public class ServiceB {
void runServiceB() {
System.out.println("ServiceB");
}
}
public class NoAdapter {
public static void main(String[] args) {
ServiceA sa = new ServiceA();
ServiceB sb = new ServiceB();
sa.runServiceA();
sb.runServiceB();
}
}어댑터 패턴이 적용된 코드
어댑터 패턴을 적용해 메서드 명을 통일해보자.
인터페이스를 토입해 조금 더 개선해보자.
2. 프록시 패턴(Proxy Pattern)
어뎁터 패턴과 비슷해 보이지만, 아래와 같은 시점으로 다른 디자인 패턴이기에 차이가 있다.
어댑터 패턴 : 호환성 제공이 목표
프록시 패턴 : 원래 객체에 대한 접근 제어가 주요 목표 (프록시 객체는 원래 객체에 대한 대리자 역할)
프록시 패턴 구현의 중요 포인트
대리자는 실제 서비스와 같은 이름으로 메서드를 구현한다. 이 때 인터페이스를 사용한다.
대리자는 실제 서비스에 대한 참조 변수를 갖는다(합성).
대리자는 실제 서비스의 같은 이름을 가진 메서드를 호출하고 그 값을 클라이언트에게 돌려준다.
대리자는 실제 서비스의 메서드 호출 전후의 별도의 로직을 수행할 수 있다.
프록시 패턴은 실제 서비스 메서드의 반환 값에 가감하는 것을 목적으로 하지 않고 제어의 흐름을 변경하거나 다른 로직을 수행하기 위해 사용한다.
실제 서비스 메서드의 반환 값에 가감하는 것을 목적으로 하는 것은 데코레이터 패턴이다.
OCP(Open Closed Principle) DIP(Dependency Inversion Principle) 원칙을 살펴볼 수 있다.
OCP : 배우가 바뀌어도 배역의 역할은 변경되지 않는다.
DIP : 자동차가 타이어에 의존해야지 스노우 타이어에 의존해서는 안된다.
프록시 패턴이 적용되지 않은 코드
프록시 패턴이 적용된 코드
프록시 패턴의 경우 실제 서비스가 가진 메서드와 같은 이름의 메서드를 사용하는데, 이를 위해서 인터페이스를 사요한다.
인터페이스를 사용하면 서비스 객체가 들어갈 자리에 프록시 객체를 대신 투입해 클라이언트 쪽에서는
실제 서비스 객체를 통해서 메서드를 호출하고 반환값을 받는지,
아니면 대리자 객체를 통해서 메서드를 호출하고 반환값을 받는지 전혀 모르게 처리할 수 있다.
3. 데코레이터 패턴(Decorator Pattern)
상속의 단점
상속은 정적이다 : 런타임 때 기존 객체의 행동을 변경할 수 없다.
자식 클래스는 하나의 부모 클래스만 가질 수 있다. 대부분 언어에서는 상속은 클래스가 동시에 여러 클래스가 동시에 여러 클래스의 행동을 상속하도록 허용하지 않는다.
프록시 패턴과 구현 방법은 동일하지만, 목적이 다르다.
프록시 패턴 : 제어의 흐름을 변경하거나 별도의 로직 처리를 목적으로 한다. 클라이언트가 받는 반환값을 특별한경우가 아니면 변경하지 않는다.
데코레이터 패턴 : 클라이언트가 받는 반환값에 장식을 더한다.
4. 싱글턴 패턴(Singleton Pattern)
싱글턴 패턴은 인스턴스를 하나만 만들어서 사용하기 위한 패턴이다.
커넥션 풀, 스레드 풀, 디바이스 설정 객체 등과 같은 경우 여러 인스턴스를 만들게 되면 불필요한 자원을 사용하게 되고, 또 예상치 못한 결과를 맞이할 수 있다.
싱글턴 패턴은 오직 인스턴스를 하나만 만들고 그것을 계속해서 사용하는 것이다.
싱글턴 패턴을 적용할 경우 의미상 두 개의 객체가 존재할 수 없다.
이를 위한 요소를 생각하면 다음과 같다.
new를 실행할 수 없도록 생성자에private접근제어자 사용유일한 단일 객체를 반환할 수 있는
static메서드 필요유일한 단일 객체를 참조할
static참조 변수 필요
static을 사용하므로 프로세스 내에서 공유가 가능한 참조 변수를 사용할 수 있게 된다.
주의점!
싱글톤 패턴은 전역 변수와 비슷한 특성을 갖게 되어서 공유 자원을 갖게 된다면 코드의 복잡성을 높일 수 있다.
때문에, 싱글톤 객체 내에는 속성을 갖지 않도록! 하는 것이 정석이다.
다만 읽기 전용 속성을 갖는 것은 문제가 되지 않는다.
싱글톤 패턴이 안티 패턴으로 불리는 이유
싱글톤 패턴은 간단하고 명료한 해결책을 제시하지만, 장기적인 유지보수성과 테스트 가능성에 악영향을 미친다.
작은 프로젝트에서는 유용할 수 있으나, 대규모 시스템에서는 전역 상태관리와 결합도 증가 문제로 인해 권장되지 않는다.
싱글톤 대신 DI 컨테이너나 팩토리 패턴 등 더 나은 설계 방식을 고려하는 것이 좋다.
5. 템플릿 메서드 패턴(Template Method Pattern)
템플릿 메서드 패턴은 상위 클래스에 골격(틀) 을 정의하고, 구체적인 구현은 하위 클래스에서 제공하는 디자인 패턴.
추상클래스, 인터페이스를 통해서 구현
"상위 클래스의 템플릿 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴"
템플릿 메서드 패턴은 의존 역전 원칙(DIP) 를 활용하고 있음을 알 수 있다.
템플릿 메서드 패턴이 적용되지 않은 코드
강아지, 고양이 클래스 모두
playWithOwner()메서드 내에서 2번째 문자열 출력을 제외하고는 다른 내용이 없다. (반복된 코드..)
템플릿 메서드 패턴이 적용된 코드
Animal이라는 추상클래스에서 틀을 만들고, 이를 상속한 하위 클래스에서 구현을 제공한다.main메서드는 구체화된 클래스(Dog,Cat)가 아닌, 추상화된 클래스(Animal)를 의존하기 때문에 DIP 원칙이 지켜진 것을 확인할 수 있다.
6. 팩터리 메서드 패턴(Factory Method Pattern)
팩터리는 공장을 의미한다. 공장은 물건을 생산하는데, 객체지향의 세계에서는 공장은 객체를 생산한다.
결국, 팩터리 메서드는 객체를 생성 반환하는 메서드를 의미한다.
여기에, 패턴이 붙으면 하위 클래스에서 팩터리 메서드를 오버라이딩해서 객체를 반환하게 하는 것을 의미한다.
팩토리 메서드 패턴 또한 의존 역전 원칙(DIP) 를 활용하고 있음을 알 수 있다.
7. 전략 패턴(Strategy Pattern)
전략 패턴을 구성하는 요소 세가지
전략 메서드를 가진 전략 객체 -> 각각의 무기. 총, 검, 활 등등 ..
전략 객체를 사용하는 컨텍스트(전략 객체의 사용자/소비자) -> 무기를 사용할 군인
전략 객체를 생성해 컨텍스트에 주입하는 클라이언트(제3자, 전략 객체의 공급자) -> 군인에게 무기를 전달해 줄 보급 장교
같은 문제를 템플릿 메서드 방법을 통해서도 해결할 수 있다.
템플릿 메서드 : 상속을 이용
전략 패턴 : 객체 주입을 이용
"클라이언트가 전략을 생성해서 전략을 실행한 컨텍스트에 주입하는 패턴"
전략 메서드 패턴은 개방 폐쇄 원칙(OCP), 의존 역전 원칙(DIP) 를 활용하고 있음을 알 수 있다.
8. 템플릿 콜백 패턴
템플릿 콜백 패턴은 전략 패턴의 변형으로, 스프링의 3대 프로그래밍 모델 중 하나인 DI(의존성 주입) 에서 사용되는 특별한 형태의 전략 패턴이다.
템플릿 콜백 패턴은 전략 패턴과 모든 것이 동일한데, 전략을 익명 내부 클래스로 정의해서 사용한다는 특징이 있다.
템플릿 콜백 패턴 또한 개방 폐쇄 원칙(OCP), 의존 역전 원칙(DIP) 를 활용하고 있음을 알 수 있다.
Last updated