Spring/additional

[Spring] 스프링이 사랑한 디자인 패턴1

sujin7837 2021. 2. 17. 19:15
반응형

[개요]

 

스프링이 사랑한 디자인 패턴1

1. Adapter Pattern(어댑터 패턴)

 

[디자인 패턴] Adapter Pattern(어댑터 패턴)

어댑터 패턴에 대한 자세한 설명은 다음 글을 참고하세요. Adapter Pattern(어댑터 패턴) [Spring] 스프링이 사랑한 디자인 패턴1 [개요] 스프링이 사랑한 디자인 패턴1 1. Adapter Pattern(어댑터 패턴) 2. Prox

sujin7837.tistory.com

2. Proxy Pattern(프록시 패턴)

 

[디자인 패턴] Proxy Pattern(프록시 패턴)

프록시 패턴에 대한 자세한 설명은 다음 글을 참고하세요. Proxy Pattern(프록시 패턴) [Spring] 스프링이 사랑한 디자인 패턴1 [개요] 스프링이 사랑한 디자인 패턴1 1. Adapter Pattern(어댑터 패턴) 2. Prox

sujin7837.tistory.com

3. Decorator Pattern(데코레이터 패턴)

 

[디자인 패턴] Decorator Pattern(데코레이터 패턴)

데코레이터 패턴에 대한 자세한 설명은 다음 글을 참고하세요. Decorator Pattern(데코레이터 패턴) [Spring] 스프링이 사랑한 디자인 패턴1 [개요] 스프링이 사랑한 디자인 패턴1 1. Adapter Pattern(어댑터

sujin7837.tistory.com

 

스프링이 사랑한 디자인 패턴2

1. Singleton Pattern(싱글턴 패턴)

2. Template Method Pattern(템플릿 메소드 패턴)

3. Factory Method Pattern(팩토리 메소드 패턴)

 

스프링이 사랑한 디자인 패턴3

1. Strategy Pattern(전략 패턴)

2. Template Callback Pattern(템플릿 콜백 패턴_견본/회신 패턴)

3. MVC 패턴

 

Adapter Pattern(어댑터 패턴)

-어댑터는 변환기(converter), 즉 서로 다른 두 인터페이스 사이에 통신이 가능하게 하는 것이라고 할 수 있습니다.

-어댑터 패턴을 활용한 예: ODBC/JDBC, JRE

-어댑터 패턴은 합성, 즉 객체를 속성으로 만들어서 참조하는 디자인 패턴으로, 호출당하는 쪽의 메소드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴입니다.

 

1. 어댑터 패턴을 적용하지 않은 경우

//ServiceA.java

public class ServiceA {
	void runServiceA() {
    	System.out.println("ServiceA");
    }
}
//ServiceB.java

public class ServiceB {
	void runServiceB() {
    	System.out.println("ServiceB");
    }
}
//ClientWithNoAdapter.java

public class ClientWithNoAdapter {
	public static void main(String[] args) {
    	ServiceA sa1=new ServiceA();
        ServiceB sb1=new ServiceB();
        
        sa1.runServiceA();
        sb1.runServiceB();
    }
}

어댑터 패턴을 적용하지 않은 경우에는 main 메소드에서 참조 변수 sa1과 sb1을 통해 호출하는 각 메소드가 비슷한 일을 하지만, 메소드명이 다른 것을 볼 수 있습니다.

 

 

2. 어댑터 패턴을 적용한 경우

//AdapterServiceA.java

public class AdapterServiceA {
	ServiceA sa1=new ServiceA();

	void runService() {
    	sb1.runServiceA();
    }
}

ServiceA를 위한 변환기 AdapterServiceA

//AdapterServiceB.java

public class AdapterServiceB {
	ServiceB sb1=new ServiceB();

	void runService() {
    	sb1.runServiceB();
    }
}

ServiceB를 위한 변환기 AdapterServiceB

//ClientWithAdapter.java

public class ClientWithAdapter {
	public static void main(String[] args) {
    	AdapterServiceA asa1=new AdapterServiceA();
        AdapterServiceB asb1=new AdapterServiceB();
        
        asa1.runService();
        asb1.runService();
    }
}

어댑터 패턴을 적용한 경우에는 main 메소드에서 클라이언트(ClientWithAdapter)가 변환기를 통해 runService()라는 동일한 메소드명으로 두 객체의 메소드를 호출하는 것을 볼 수 있습니다.

 

 

 

Proxy Pattern(프록시 패턴)

-프록시는 대리자/대변인이라는 뜻을 가진 단어로, 이는 다른 누군가를 대신해 그 역할을 수행하는 존재를 말합니다.

-프록시는 제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴입니다.

 

1. 프록시 패턴을 적용하지 않은 경우

//Service.java

public class Service {
	public String runSomething() {
    	return "서비스 짱!!!";
    }
}
//ClientWithNoProxy.java

public class ClientWithNoProxy {
	public static void main(String[] args) {
    	//프록시를 이용하지 않은 호출
        Service service=new Service();
        System.out.println(service.runSomething());
    }
}

 

2. 프록시 패턴을 적용한 경우

//IService.java

public interface IService {
	String runSomething();
}

IService는 인터페이스 입니다.

프록시 패턴의 경우, 실제 서비스 객체가 가진 메소드와 같은 이름의 메소드를 사용하는데, 이를 위해 인터페이스를 사용합니다. 인터페이스를 사용하면 서비스 객체가 들어갈 자리에 대리자 객체를 대신 투입해 클라이언트 쪽에서는 실제 서비스 객체를 통해 메소드를 호출하고 반환값을 받는지, 대리자 객체를 통해 메소드를 호출하고 반환값을 받는지 전혀 모르게 처리할 수도 있습니다.

 

//Service.java

public class Service implements IService {
	public String runSomething() {
    	return "서비스 짱!!!";
    }
}

IService 인터페이스를 구현한 Service

 

//Proxy.java

public class Proxy implements IService {
	IService service1;

	public String runSomething() {
    	System.out.println("호출에 대한 흐름 제어가 주목적, 반환 결과를 그대로 전달");
        
        service1=new Service();
        return service1.runSomething();
    }
}

IService 인터페이스를 구현한 Proxy

 

//ClientWithProxy.java

public class ClientWithProxy {
	public static void main(String[] args) {
    	//프록시를 이용한 호출
        IService proxy=new Proxy();
        System.out.println(proxy.runSomething());
    }
}

프록시를 사용하는 ClientWithProxy

 

프록시 패턴의 중요 포인트

  • 대리자는 실제 서비스와 같은 이름의 메소드를 구현합니다. 이때 인터페이스를 사용합니다.
  • 대리자는 실제 서비스에 대한 참조 변수를 가집니다.(합성)
  • 대리자는 실제 서비스의 같은 이름을 가진 메소드를 호출하고 그 값을 클라이언트에게 돌려줍니다.
  • 대리자는 실제 서비스의 메소드 호출 전후에 별도의 로직을 수행할 수도 있습니다.

 

Decorator Pattern(데코레이터 패턴)

-데코레이터는 장식자라는 뜻을 가지고 있으며, 원본에 장식을 더하는 패턴이라는 것이 이름에 잘 드러나 있습니다.

-데코레이터 패턴은 프록시 패턴과 구현 방법이 같은데, 다만 프록시 패턴은 클라이언트가 최종적으로 돌려 받는 반환값을 조작하지 않고 그대로 전달하는 반면 데코레이터 패턴은 클라이언트가 받는 반환값에 장식을 덧입힙니다.

-데코레이터 패턴은 메소드 호출의 반환값에 변화를 주기 위해 중간에 장식자를 두는 패턴입니다.

-프록시 패턴과 데코레이터 패턴 비교

프록시 패턴 -제어의 흐름을 변경하거나 별도의 로직 처리를 목적으로 합니다.
-클라이언트가 받는 반환값을 특별한 경우가 아니면 변경하지 않습니다.
데코레이터 패턴 -클라이언트가 받는 반환값에 장식을 더합니다.

 

//IService.java

public interface IService {
	public abstract String runSomething();
}

IService는 인터페이스 입니다.

 

//Service.java

public class Service implements IService {
	public String runSomething() {
    	return "서비스 짱!!!";
    }
}

IService 인터페이스를 구현한 Service

 

//Decorator.java

public class Decorator implements IService {
	IService service;

	public String runSomething() {
    	System.out.println("호출에 대한 장식 주목적, 반환 결과에 장식을 더하여 전달");
        
        service=new Service();
        return "정말" + service.runSomething();
    }
}

IService 인터페이스를 구현한 Decorator

 

//ClientWithDecorator.java

public class ClientWithDecorator {
	public static void main(String[] args) {
        IService decorator=new Decorator();
        System.out.println(decorator.runSomething());
    }
}

데코레이터를 사용하는 ClientWithDecorator

 

데코레이터 패턴의 중요 포인트

  • 장식자는 실제 서비스와 같은 이름의 메소드를 구현합니다. 이때 인터페이스를 사용합니다.
  • 장식자는 실제 서비스에 대한 참조 변수를 가집니다.(합성)
  • 장식자는 실제 서비스의 같은 이름을 가진 메소드를 호출하고, 그 반환값에 장식을 더해 클라이언트에게 돌려줍니다.
  • 장식자는 실제 서비스의 메소드 호출 전후에 별도의 로직을 수행할 수도 있습니다.
반응형