2021. 8. 16. 13:15ㆍCSE/JAVA
- 디자인 패턴은 객체 지향의 특성 중 상속, 인터페이스, 합성 (객체를 속성으로 사용)을 이용한다.
1. 어댑터 패턴(Adpater Pattern)
- 어댑터 (Adapter) : 변환기. 즉, 서로 다른 인터페이스 사이에 통신이 가능하게 하는 것이다.
- 어댑터 패턴은 개방 폐쇄 원칙을 활용한 설계 패턴이라고 할 수 있다.
(1) ServiceA.java
public class ServiceA {
void runServiceA(){
System.out.println("ServiceA");
}
}
(2) ServiceB.java
public class ServiceB {
void runServiceB(){
System.out.println("ServiceB");
}
}
(3) AdapterServiceA.java
public class AdapterServiceA {
ServiceA sa1 = new ServiceA();
void runService(){
sa1.runServiceA();
}
}
(4) AdapterServiceB.java
public class AdapterServiceB {
ServiceB sb1 = new ServiceB();
void runService(){
sb1.runServiceB();
}
}
(5) ClientWithAdapter.java
public class ClientWithAdapter {
public static void main(String[] args) {
AdapterServiceA asa1 = new AdapterServiceA();
AdapterServiceB asb1 = new AdapterServiceB();
asa1.runService();
asb1.runService();
}
}
- (3),(4)는 (1),(2)의 메서드를 runService()라고 하는 같은 이름의 메서드로 호출해서 사용할 수 있게 해주는 변환기다.
- 어댑터 패턴 : 호출당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴
2. 프록시 패턴(Proxy Pattern)
- 프록시 : 대리자, 대변인
(1) IService.java (인터페이스)
public interface IService {
String runSomething();
}
(2) Service.java
public class Service implements IService{
public String runSomething(){
return "서비스 짱!!!";
}
}
(3) Proxy.java
public class Proxy implements IService{
IService service1;
public String runSomething(){
System.out.println("호출에 대한 흐름 제어가 주목적, 반환 결과를 그대로 전달");
service1 = new Service();
return service1.runSomething();
}
}
(4) ClientWithProxy.java
public class ClientWithProxy {
public static void main(String[] args) {
IService proxy = new Proxy();
System.out.println(proxy.runSomething());
}
}
(5) 프록시 패턴을 적용한 후 시퀀스 다이어그램
(6) 프록시 패턴의 중요 포인트
- 대리자는 실제 서비스와 같은 이름의 메서드를 구현한다. 이때 인터페이스를 사용한다
- 대리자는 실제 서비스에 대한 참조 변수를 갖는다(합성)
- 대리자는 실제 서비스의 같은 이름을 가진 메서드를 호출하고 그 값을 클라이언트에게 돌려준다
- 대리자는 실제 서비스의 메서드 호출 전후에 별도의 로직을 수행할 수도 있다
- 프록시 패턴은 제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴
- 위의 예제에서 살펴본 프록시 패턴은 개방 폐쇄 원칙과 의존 역전 원칙이 적용된 설계 패턴이다.
3. 데코레이터 패턴(Decorator Pattern)
- 데코레이터 : 장식자
- 데코레이터 패턴은 프록시 패턴과 구현 방법이 같지만, 클라이언트가 받는 반환값에 장식을 덧입힌다는 점이 다르다.
- 데코레이터 패턴 : 메서드 호출의 반환값에 변화를 주기 위해 중간에 장식자를 두는 패턴
(1) 데코레이터 패턴의 중요 포인트
- 대리자는 실제 서비스와 같은 이름의 메서드를 구현한다. 이때 인터페이스를 사용한다
- 대리자는 실제 서비스에 대한 참조 변수를 갖는다(합성)
- 대리자는 실제 서비스의 같은 이름을 가진 메서드를 호출하고, 그 반환값에 장식을 더해 클라이언트에게 돌려준다
- 대리자는 실제 서비스의 메서드 호출 전후에 별도의 로직을 수행할 수도 있다
4. 싱글턴 패턴 (Singleton Pattern)
- 싱글턴 패턴이란 인스턴스를 하나만 만들어 사용하기 위한 패턴이다.
- 따라서 이를 구현하라면 다음 세 가지가 반드시 필요하다.
- new를 실행할 수 없도록 생성자에 private 접근 제어자를 지정한다
- 유일한 단일 객체를 반환할 수 있는 정적 메서드가 필요하다
- 유일한 단일 객체를 참조할 정적 참조 변수가 필요하다
public class Singleton {
static Singleton singletonObject; //정적 참조 변수
private Singleton(){}; //private 생성자
//객체 반환 정적 메서드
public static Singleton getInstance(){
if (singletonObject == null){
singletonObject = new Singleton();
}
return singletonObject;
}
}
public class Client {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
Singleton s3 = Singleton.getInstance();
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
s1 = null;
s2 = null;
s3 = null;
}
}
- 단일 객체인 경우, 결국 공유 객체로 사용되기 때문에 속성을 갖지 않게 하는 것이 정석
=> 단일 객체가 속성을 갖게 되면 하나의 참조 변수가 변경한 단일 객체의 속성이 다른 참조 변수에 영향을 미치기 때문이다
=> 다만 읽기 전용 속성을 갖는 것과 다른 단일 객체에 대한 참조를 속성으로 가진 것은 괜찮음
- 기억해 둘 싱글턴 패턴의 특징
- private 생성자를 갖는다
- 단일 객체 참조 변수를 정적 속성으로 갖는다
- 단일 객체 참조 변수가 참조하는 단일 객체를 반환하는 getInstance() 정적 메서드를 갖는다.
- 단일 객체는 쓰기 가능한 속성을 갖지 않는 것이 정석이다.
- 싱글턴 패턴 : 클래스의 인스턴스, 즉, 객체를 하나만 만들어 사용하는 패턴
'CSE > JAVA' 카테고리의 다른 글
[자바 객체 지향] 스프링이 사랑한 디자인 패턴 2 (0) | 2021.09.06 |
---|---|
자바 JDBC (0) | 2021.08.16 |
[자바 객체 지향] 객체 지향 설계 5원칙 : ISP, DIP (0) | 2021.08.09 |
[자바 객체 지향] 객체 지향 설계 5원칙 : SRP, OCP, LSP (0) | 2021.08.07 |
[자바 객체 지향] static 블록 (0) | 2021.08.07 |