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

개발자 로그·2021년 5월 27일
0
post-thumbnail

스프링 프레임워크

"자바 엔터프라이즈 개발을 평하게 해주는 오픈소스 경량급 애플리케이션 프레임워크"
"OOP 프레임워크"


어댑터 패턴 ( Adapter Pattern )

"호출당하는 쪽의 메소드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴"

ex) JDBC, JRE

  • 서로 다른 두 인터페이스 사이에 통신이 가능하게 하는 것
  • 합성, 즉 객체의 속성으로 만들어서 참조하는 디자인 패턴

프록시 패턴 ( Proxy Pattern )

"제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴"

  • 실제 서비스 메서드의 반환값에 가감하는 것을 목적으로 하지 않고 제어의 흐름을 변경하거나 다른 로직을 수행하기 위해 사용한다.
  • 프록시 패턴은 개방 폐쇄 원칙(OCP)과 의존 역전 원칙(DIP)이 적용된 설계 패턴이다.
  • 제어의 흐름을 변경하거나 별도의 로직 처리를 목적으로 한다.
  • 클라이언트가 받는 반환값을 특별한 경우가 아니면 변경하지 않는다.
public interface IService {
	String runSomthing();
}

public class Service implements IService {
	@Override
	public String runSomthing() {		
		return "서비스1";
	}
}

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

public class ClientWithProxy {
	public static void main(String[] args) {
		// 프록시를 이용한 호출
		IService proxy = new Proxy();
		System.out.println(proxy.runSomthing());
	}
}
/** 출력값
호출에 대한 흐름 제어가 주목적, 반환결과를 그대로 전달.
서비스1
*/

데코레이션 패턴 ( Decorator Pattern )

"메서드 호출의 반환값에 변화를 주기 위해 중간에 장식자를 두는 패턴"

  • 프록시 패턴과 구현 방법은 같다.
  • 클라이언트가 받는 반환값에 장식을 더한다.

싱글턴 패턴 ( 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) {
		// private 생성자이므로 new를 통해 인스턴스를 생성할 수 없음
		// Singleton s = new Singleton();
		
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		Singleton s3 = Singleton.getInstance();
		
		System.out.println(s1);
		System.out.println(s2);
		System.out.println(s3);		
		/**
		 com.grace.oop.singleton.Singleton@26f0a63f
		 com.grace.oop.singleton.Singleton@26f0a63f
		 com.grace.oop.singleton.Singleton@26f0a63f
		 */
	}
}

템플릿 메서드 패턴 ( Template Method Pattern )

" 상위 클래스의 경본 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴"

  • 의존 역전 원칙(DIP)을 활용하고 있다

팩터리 메서드 패턴 ( Factory Mrthod Pattern )

"오버라이드된 메서드가 객체를 반환하는 패턴"

  • 팩터리 메서드는 객체를 생성 반환하는 메서드이다.
  • 팩터리 패턴은 하위 클래스에서 팩터리 메서드를 오버라이딩해사 객체를 반환하게 하는 것.
  • 의존 역전 원칙(DIP)을 활용하고 있다

전략 패턴 ( Strategy Pattern )

"클라이언트가 전략을 생성해 전략을 실행할 컨텍스트에 주입하는 패턴"

< 필요한 요소 >
- 전략 메서드를 가진 전략 객체
- 전략 객체를 사용하는 컨텍스트 (전략 객체의 사용자/소비자)
- 전략 객체를 생성해 컨텍스트에 주입하는 클라이언트 (제3자, 전략 객체의 공급자)
  • 개방 폐쇄 원칙(OCP)과 의존 역전 원칙(DIP)이 적용된 설계 패턴이라고 짐잘할 수 있다.
public interface Strategy {
	public abstract void runStrategy();
}

public class StrategyGun implements Strategy{
	@Override
	public void runStrategy() {
		System.out.println("총: 탕 탕 탕 탕");
	}
}

public class StrategyBow implements Strategy {
	@Override
	public void runStrategy() {
		System.out.println("활: 슝 슝 슝");
	}
}

public class Soldier {
	void runContext(Strategy strategy) {
		System.out.println("전투 시작");
		strategy.runStrategy();
		System.out.println("전투 종료");
	}
}

public class Client {
	public static void main(String[] args) {
		Strategy strategy = null;
		Soldier rambo = new Soldier();

		// 총을 람보에게 전달해서 전투를 수행하게 한다.
		strategy = new StrategyGun();
		rambo.runContext(strategy);
  	System.out.println();

		// 활을 람보에게 전달해서 전투를 수행하게 한다.
		strategy = new StrategyBow();
		rambo.runContext(strategy);
	}
}

/** 출력값
전투 시작
총: 탕 탕 탕 탕
전투 종료

전투 시작
활: 슝 슝 슝
전투 종료
*/

탬플릿 콜백 패턴 ( Template Callback Pattern - 견본/회신 패턴 )

"전략을 익명 내부 클래스로 구연한 전략 패턴"

  • 전략 패턴의 변형으로 DI(의존성 주입)에서 사용하는 특별한 형태의 전략 패턴
  • 전략을 익명 내부 클래스로 정의해사 사용한다는 특징이 있다.
  • 개방 폐쇄 원칙(OCP)과 의존 역전 원칙(DIP)이 적용된 설계 패턴이다.
public interface Strategy {
	public abstract void runStrategy();
}

public class Soldier {
	void runContext(String weapon) {
		System.out.println("전투 시작");
		executeWeapon(weapon).runStrategy();
		System.out.println("전투 종료");
	}
	
	private Strategy executeWeapon(final String weapon) {
		return new Strategy() {
			@Override
			public void runStrategy() {
				System.out.println(weapon);
			}
		};
	}
}

public class Client {
	public static void main(String[] args) {
		Soldier rambo = new Soldier();
		rambo.runContext("총 총 총 총 총");	
		System.out.println();
		rambo.runContext("활 활 활 활 활");

	}
}
/** 출력값
전투 시작
총 총 총 총 총
전투 종료

전투 시작
활 활 활 활 활
전투 종료
*/
profile
성장하는 개발자

0개의 댓글