#Chain of Responsibility

 

 

1. 개념

 

Chain of Responsibility(책임 사슬)패턴

어떤 하나의 문제가 발생했을 경우

그 문제의 처리를 담당하는 여러개의 처리기를 두고

순서대로 처리해 나가는 패턴을 말한다.

 

자바에서 바로 try/catch/finally

책임 사슬 패턴을 적용한 예이다.

try{}블럭 안에서 예외가 발생했을 경우

catch{}블럭으로 이동하는데

어떤 예외인지에 따라 어떤 catch{}블럭이 실행되는지 결정되는 행위가

역할 사슬 패턴이라는 것이다.

 

 

2. Why? 왜 사용해야 할까?

 

프로젝트를 수행하다보면 무수히 많은 객체들을 생성하게 된다.

자신이 만든 모든 객체의 위치와 내용을 다시 기억해 내기란

실질적으로 힘든 경우가 있다.

이처럼

어떤 요청에 대해 처리해주는 객체의 위치를 파악하기 어려운 상황에 대비하여

이러한 요청을 처리해주는 객체들의 집합체나 계층화가 되어있으면

사용자는 굳이 객체의 위치를 알 필요없이

손쉽게 요청을 처리할 수 있다.

 

 

3. 장단점

 

책임 사슬 패턴을 사용하면 모든 후보 객체들을

다 알 필요없이 단순하게

자신과 연결된 단 하나의 후보 객체만 알면된다.

이처럼 객체들 간의 상호작용 과정을 단순화시키기에

객체 간의 결합도가 낮아지는 방법이 된다.

 

객체의 책임을 여러 객체에게 분산시키는 과정에서

상속을 이용하므로

객체의 기능을 추가, 삭제 및 수정하기 용이하다.

 

그러나 이 방식은 요청이 처리된다는 보장이 없다.

객체들 간의 연결고리가 잘 정의되어 있어야 하며

객체들 중 아무도 요청을 처리하지 못했을 경우

요청은 그냥 버려질 수 있다는 가능성이 있다.

이때 Exception을 던지는 방식 등으로 대처를 할 수 있다.

 

 

4. 클래스 다이어그램

 

5. 예제 코드

 

코드 예제는 java에서 Exception에서 아이디어가 떠올랐다.

실제 구동되는 동작은 다르지만 이해가 수월하길 바란다.

 

Exception 객체들은 모두 Problem 객체에 의해 관리되고 있으며

하위 클래스에서 자신이 처리할 수 있는 에러인지 확인하고

객체를 생성하는 코드를 구현해보았다.

public abstract class Problem {
	
	private static Problem[] list = {new SocketException(), new NullPointException(), new IOException()};
	protected static Integer num = 0;
	protected static String msg;
	
	public static Problem next(String error) {
		msg = error;
		
		if(num == list.length) {
			System.out.println("어떤 에러인지 확인 불가능");
			return null;
		}
		
		return list[num++].cause();
	}

	
	public abstract Problem cause();
}

 

하위 클래스 Exception객체들은 다음과 같이 구현되었다.

public class SocketException extends Problem{

	@Override
	public Problem cause() {
		if("socket".equals(msg)) {
			System.out.println("소켓 문제 발생! SocketException 객체 생성");
			num = 0;
			return this;
		}
		
		//다음 객체 ㄱㄱ
		return next(msg);
	}
}

public class NullPointException extends Problem{

	@Override
	public Problem cause() {
		
		if("null".equals(msg)) {
			System.out.println("객체에 Null 값이 들어감. NullPointException 객체 생성");
			num = 0;
			return this;
		}
		
		//다음 객체 ㄱㄱ
		return next(msg);
		
	}
}

public class IOException extends Problem{

	@Override
	public Problem cause() {
		
		if("IO".equals(msg)) {
			System.out.println("입력 값 오류 발생! IOException 객체 생성");
			num = 0;
			return this;
		}
		
		//다음 객체 ㄱㄱ
		return next(msg);
	}

}

 

클라이언트에서 에러가 발생해 Problem 객체를 호출하고

문제의 원인을 물어보는 코드를 구현했다.

public class Client {

	public static void main(String[] args) {
		
		System.out.println("에러 발생!");
		System.out.println("");
		
		
		//입력 오류로 에러가 발생한 경우
		System.out.println("입력 오류가 발생한 경우");
		Problem problem1 = Problem.next("IO");
		System.out.println("");
		
		//객체에 null값으로 에러가 발생한 경우
		System.out.println("null 값으로 에러가 난 경우");
		Problem problem2 = Problem.next("null");
			

	}

}

 

정리하자면 Client에서 오류가 발생하였고

Problem 객체를 이용하여 오류에 해당하는 객체를 생성하는 과정의 코드이다.

결과는 다음과 같이 나온다.

 

6. 참고

 

https://leetaehoon.tistory.com/64

https://ehclub.co.kr/2210

https://blog.naver.com/2feelus/220655715030

http://egloos.zum.com/iilii/v/3863886

GoF의 디자인 패턴

 

 

Made by 꿩

 

 

'스터디 > GoF의 디자인패턴' 카테고리의 다른 글

Strategy Pattern  (0) 2019.04.30
Template Method Pattern  (0) 2019.04.30
Decorator Pattern  (0) 2019.04.28
Factory Method Pattern  (0) 2019.04.23

#Strategy Pattern

 

 

1. 개념

 

전략 패턴(Strategy Pattern)이란 알고리즘 대체를 위해

동일한 목적을 지닌 알고리즘군을 인터페이스로 묶고

캡슐화하여 서로 대체가 가능하게 사용하는 것을 말한다.

 

예를 들어

종로에서 충무로를 가는 방법을 생각해보자

시간이 들더라도 걸어갈 수 있으며

택시를 타도 되고

버스나 지하철을 탈 수도 있다.

각각의 시간과 비용은 모두 다르지만

한 곳을 간다는 목적은 동일하다.

 

이처럼 비슷한 목적을 지닌 알고리즘을 묶어서

서로 상호교환이 가능하도록 만드는 패턴을

전략 패턴이라 한다.

 

 

2. Why? 왜 사용해야 할까?

 

구현된 알고리즘은 다르지만 동일한 목적을 지닌 클래스들이 존재할 때

전략 패턴을 사용하는 것이 좋다.

한 가지 알고리즘을 평소에 사용하더라도

참조하는 클래스의 변경이나 제거 등 여러가지 상황이 발생하거나

사용하는 시점에 따라서 알고리즘을 변경해야 하는 상황이 있을 수 있다.

이런 경우 언제든지 알고리즘을 쉽게 대체할 필요성이 있으며

전략 패턴을 사용하게 된다면

새로운 알고리즘을 추가하는 확장이 용이하기 때문이다.

 

 

3. 장단점

 

전략 패턴은 알고리즘의 변경 부분만을 따로 빼내어 구현한 것이므로

알고리즘마다 사용되는 코드 중복을 방지할 수 있으며

알고리즘을 쉽게 대체할 수 있고

확장성이 용이하여 다양한 알고리즘을 쉽게 추가할 수도 있다.

클라이언트와 독립적이기 때문에 알고리즘 변경에 대해서도 강하다.

 

그러나

알고리즘이 늘어날수록 객체도 무한정 늘어나며

클라이언트가 사용할 객체를 직접 결정해야 하기 때문에

많은 알고리즘에 대한 성능과 효율을 알고 있어야 하고

서로간의 차이를 알아야 하는데

직접 만든 것이 아니라면 부담스러울 수 있다.

 

 

4. 추가내용

 

앞서 템플릿 메소드 패턴에서 언급했듯이

보통 전략 패턴은 템플릿 메소드 패턴과 비교가 된다.

전략 패턴은 템플릿 메소드 패턴과 구성은 동일하지만 사용목적이 다르다고 볼 수 있다.

템플릿 메소드 패턴 공통된 메소드를 통해서 코드의 중복없이 사용하는 것이고

전략 패턴 상황에 맞는 필요한 전략을 선택하기 위해 사용하는 패턴이다.

 

그리고

객체의 행위를 유연하게 확장하고 구조가 데코레이터 패턴과 유사하지만

전략 패턴코드 내부의 알고리즘을 변화시키고

데코레이터 패턴코드 외부의 리턴 값을 변화시킨다는 점에서 차이가 있다.

 

 

5. 클래스 다이어그램

 

 

6. 예제 코드

 

포켓몬을 잡는 코드를 보며 전략 패턴에 대해서 알아보자

당신은 포켓몬 게임을 시작하며 스타팅 포켓몬으로 치코리타를 받았다.

당신에겐 절실히 다른 포켓몬이 필요하여 잠만보를 잡으려 한다.

당신에겐 몬스터볼, 하이퍼볼, 마스터볼이 있다.

세 개의 몬스터볼을 전략 1,2,3으로 구현하였고 몬스터볼 인터페이스로 묶어봤다.

public interface MonsterBall {
	
	public int throwBall();

}

public class Strategy1 implements MonsterBall{

	@Override
	public int throwBall() {
		System.out.println("몬스터 볼을 던진다.(확률:20%, 가격: 천원)");
		return 1;
	}
}

public class Strategy2 implements MonsterBall{

	@Override
	public int throwBall() {
		System.out.println("하이퍼볼을 던진다.(확률:50%, 가격: 삼천원)");
		return 4;
	}
}

public class Strategy3 implements MonsterBall{

	@Override
	public int throwBall() {
		System.out.println("마스터볼을 던진다.(확률:100%, 가격: 백만원)");
		return 9;
	}
}

 

Player1 캐릭터는 포켓몬을 잡기 위해 몬스터볼을 던질 수 있게 만들었고

전략을 파라미터로 받는다.

public class Player1 {
	
	public int getPokemon(MonsterBall monsterBall) {
		
		return monsterBall.throwBall();
		
	}
}

 

당신은 나중을 위해 하이퍼볼과 마스터볼을 아껴놓기로 하고

일반 몬스터볼(전략1)을 던져보기로 결정했다.

import java.util.Random;

public class PokemonGame {

	public static void main(String[] args) {
		
		Player1 player1 = new Player1();
		
		System.out.println("야생의 잠만보가 출현했습니다.");
		Random random = new Random();
		
		int ran = random.nextInt(10);
		int prob = player1.getPokemon(new Strategy1());
		
		if(ran <= prob) {
			System.out.println("잠만보를 잡았습니다!");
		} else {
			System.out.println("아쉽게 놓쳤다, 잠만보가 도망쳤다.");
		}

	}
}

 

결과는 다음과 같다.

 

 

7. 참고

 

https://rearrangingall.blogspot.com/2017/01/01-strategy-pattern.html

https://niceman.tistory.com/133

https://kimsunzun.tistory.com/entry/Strategy%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B4

GoF의 디자인 패턴

 

 

Made by 꿩

'스터디 > GoF의 디자인패턴' 카테고리의 다른 글

Chain of Responsibility  (0) 2019.05.06
Template Method Pattern  (0) 2019.04.30
Decorator Pattern  (0) 2019.04.28
Factory Method Pattern  (0) 2019.04.23

#Template Method Pattern

 

 

1. 개념

 

탬플릿 메소드 패턴여러 클래스에서 공통된 행위는 상위 클래스에서 정의하고

하위 클래스에서 각각의 상세부분을 구현하는 것을 말한다. 

 

템플릿이란 큰 구조를 정의한 틀로서

전체적인 틀은 동일하되 상세적인 부분은 다르게 찍어낼 수 있는 것을 말한다.

블로그를 꾸며본 사람은 알겠지만

대부분 블로그들은 여러 디자인의 템플릿을 제공해주고

일정한 틀 안에서 자신만의 블로그를 쉽게 꾸밀 수 있도록 도와준다.

 

이러한 개념을 객체에 적용한다면

여러 객체들은 추상클래스 또는 인터페이스를 통해서

동일한 이름의 메소드를 구현하되

기타 메소드는 각 객체에 맞게 구현하는 것이다.

 

 

2. Why? 왜 사용해야 할까?

 

객체를 생성하다 보면 비슷한 동작을 하는 객체들이 많다.

비슷한 동작을 하는 객체들에서 변하지 않는 부분을 한 번 정의해 놓고

다양해질 수 있는 부분은 하위 클래스에 정의할 수 있는 경우

템플릿 메소드 패턴을 이용하면

코드의 중복을 피할 수 있고

상위 클래스로 묶여있기 때문에

if - else 문을 쓰지 않고 다양한 객체를 생성할 수 있다.

 

 

3. 장단점

 

템플릿 메소드의 장점은 쉬운 확장성에 있다.

일정한 틀이 있기 때문에

추상 클래스를 상속받아

쉽게 하위 클래스를 생성, 추가해 나갈 수 있다.

 

또한 앞서 언급했듯이

로직을 공통화하게 되면

비슷한 알고리즘은 일일히 기술할 필요가 없어져

코드의 중복을 줄일 수 있다.

 

그러나 템플릿 메소드는 조심해야한다.

상위 클래스가 관리하는 하위 클래스가 많을 때

상위 클래스를 수정하게 될 때

모든 하위 클래스들을 일일히 수정해야 하는 상황이 발생한다.

 

 

4. 추가내용

 

템플릿 메소드처럼 상속을 통해 확장하는 패턴이 팩토리 메소드 패턴이다.

두 패턴은 비슷하지만 명확한 차이가 있다.

팩토리 메소드 패턴객체의 생성을 리턴하는 메소드를 만드는 것이고

템플릿 메소드 패턴객체의 행위를 동작하는 공통된 메소드를 만드는 것이다.

 

템플릿 메소드 패턴과 비교할 때 빠지지 않는 패턴은 바로 전략 패턴이다.

전략 패턴은 템플릿 메소드 패턴과 구성은 동일하지만 사용관점이 틀리다고 볼 수 있다.

템플릿 메소드 패턴객체의 행위를 동작하는 공통된 메소드를 만드는 것이고

전략 패턴은 동일 이름의 메소드 중 상황에 맞는 필요한 전략을 사용하는 패턴이다.

 

 

5. 클래스 다이어그램

6. 예제 코드

 

탑 라인에서 티모와 블라디가 맞붙는다.

서로의 스킬과 소환사의 주문을 출력하는 코드를 통해

템플릿 메소드 패턴을 알아보자.

 

먼저 탑라이너라는 추상클래스에는 점멸과 순간이동 메소드가 구현되어 있고

스킬과 궁극기 스킬은 추상 메소드로 명시되어 있다.

public abstract class TopLiner {
	
	public void flashing() {
		System.out.println("점멸!");
	}
	
	public void warp() {
		System.out.println("순간이동!");
	}
	
	public abstract void skill();
	
	public abstract void ultimateSkill();
	
}

 

티모와 블라디는 추상클래스를 상속받아 각자의 스킬을 구현한다.

public class Teemo extends TopLiner{

	@Override
	public void skill() {
		System.out.println("실명!");
		
	}

	@Override
	public void ultimateSkill() {
		System.out.println("독버섯!");
	}

}

public class Vladimir extends TopLiner{

	@Override
	public void skill() {
		System.out.println("수혈!");
		
	}

	@Override
	public void ultimateSkill() {
		System.out.println("혈사병!");
		
	}

}

 

메인 클래스에서 각자의 스킬 및 소환사 주문을 확인하면

다음의 결과가 나온다.

public class SummorsGorge {

	public static void main(String[] args) {
		
		System.out.println("소환사의 협곡에 오신 것을 환영합니다.\n");
		
		TopLiner top1 = new Teemo();
		TopLiner top2 = new Vladimir();
		
		System.out.println("티모 스킬");
		top1.skill();
		top1.ultimateSkill();
		System.out.println("소환사 주문");
		top1.flashing();
		top1.warp();
		
		System.out.println("");
		
		System.out.println("블라디 스킬");
		top2.skill();
		top2.ultimateSkill();
		System.out.println("소환사 주문");
		top2.flashing();
		top2.warp();
		
	}

}

 

 

7. 참고

 

https://leetaehoon.tistory.com/47

https://dlucky.tistory.com/145

https://kimddochi.tistory.com/55

https://hyeonstorage.tistory.com/146

https://rearrangingall.blogspot.com/2017/01/01-strategy-pattern.html

GoF의 디자인 패턴

 

 

Made by 꿩

'스터디 > GoF의 디자인패턴' 카테고리의 다른 글

Chain of Responsibility  (0) 2019.05.06
Strategy Pattern  (0) 2019.04.30
Decorator Pattern  (0) 2019.04.28
Factory Method Pattern  (0) 2019.04.23

#Decorator Pattern

 

 

1. 개념

 

데코레이터 패턴(Decorator pattern)은 객체의 추가적인 요건을 동적으로 추가하는 패턴이다.

Decorator는 글자 그대로 장식가로서, 중심이 되는 객체가 반환하는 값에

추가적으로 더해져서 결과값을 반환합니다. 

 

쉽게 스타벅스를 생각해보자

스타벅스는 자신만의 커스터마이징 음료를 만들 수 있다.

나같은 경우는 그린 티 크림 프라푸치노(Green Tea Cream Frappuccino)를 주문해서

에스프레소 샷 추가, 저지방 우유, 라이트 시럽, 휘핑크림, 자바칩 갈아 만든

커스터마이징 음료를 산다.

 

이와 같이 하나의 객체에 옵션들을 여러개 추가해서

만드는 패턴을 장식하는 것과 같다하여

데코레이터 패턴이라 한다.

 

 

 

(출처: http://i.stack.imgur.com/O7pqc.png )

 

2. Why? 왜 사용해야 할까?

 

하나의 객체에 부가적인 기능을 덧붙여야 할 때가 있다.

또한 동일한 객체를 여러개 만들어야 하지만

각기 다른 기능을 첨가할 필요가 있을 때

데코레이터 패턴을 이용하면

많은 객체에게 다양한 부가기능을 쉽고 빠르게 적용할 수 있다.

 

 

 

 

3. 장단점

 

데코레이터 패턴의 핵심은

중심이 되는 객체를 놔두고 추가적인 사항을 첨가하는 방식이라

객체에 기능을 추가 또는 삭제 할 때

 중심이 되는 객체를 수정하지 않고 동적으로 추가 또는 삭제할 수 있다.

객체지향의 원칙 중 OCP에 충실한 패턴인데

OCP는 Open-Close Principle로서 확장에는 열려있고 변경에는 닫혀 있어야 한다는 원칙이다.

 

데코레이터 패턴을 사용하게 되면

기존 객체는 변경하지 않고 자유로운 확장을 구현할 수 있으며

기존 객체가 수정되더라도 또는 데코레이터가 수정되더라도

해당 클래스의 내용만 수정해주면 되기 때문에 변경에 대해서도 닫혀있다.

 

또한,

기본적인 데이터에 첨가하는 데이터가 일정하지 않고 다양할 때

데코레이터 패턴을 사용하면 효율적으로 사용할 수 있다.

 

반면에

데코레이터를 너무 많이 사용하게 되면

자질한 객체가 많이 추가될 수 있고

오히려 코드가 복잡해 질 수 있다는 단점이 있다.

 

 

4. 추가내용

 

비슷하게 확장을 하는 상속과 데코레이터 패턴의 차이는 무엇일까?

상속은 하위 클래스를 생성하는 방법으로 확장을 하며

데코레이터 패턴은 기본 객체에 추가하는 객체를 생성하는 방법으로 확장을 한다.

상속은 오버라이딩을 통해 기능을 전부 명시해 줘야 하지만

데코레이터 패턴은 기본 기능은 놔두고 추가되는 기능만 명시해 줄 수 있다는 차이가 있다.

 

데코레이터 패턴은 여러 패턴들과 유사한 구조를 가지고 있다.

 

다양하고 일정하지 않은 여러 객체들을 하나의 객체로 묶는 것Composite 패턴이라 하는데

데코레이터 패턴은 한 구성요소 만을 갖는 Composite 패턴이라 볼 수 있다.

그러나 목적에서 차이가 있다.

Composite 패턴은 목적이 생성되어 있는 객체들 간의 합성에 있고

데코레이터 패턴은 목적이 객체에 새로운 행동을 추가하는 데에 있다.

 

Strategy 패턴유사한 행위를 캡슐화하는 인터페이스를 정의하여

객체들의 행위를 유연하게 확장하는 방법으로 데코레이터 패턴과 구조가 비슷하다.

하지만 Strategy 패턴은 객체의 내부를 변화시키며

데코레이터 패턴은 새로운 객체를 추가하여 객체를 변경한다는 점에서 차이가 있다.

 

마지막으로 Adaptor 패턴서로 다른 인터페이스를 통일시켜 사용하는 패턴으로서

데코레이터가 기준 객체와 부가 객체를 연결하는 어댑터 역할을 하는 것과 유사하다.

그러나 데코레이터 패턴은 어댑터 패턴과 달리 인터페이스를 변경 없이

객체에 새로운 행동을 추가한다는 점에서 차이가 있다.

 

 

5. 클래스 다이어그램

 

 

6. 예제 코드

 

스타벅스에서 그린티 크림 프라푸치노에

샷추가, 저지방 우유, 자바칩을 추가했을 때 가격을 알아본다.

 

public interface StarbucksMenu {
	
	public int cost();

}

public class GreenTeaCreamFrappuccino implements StarbucksMenu{
	
	public GreenTeaCreamFrappuccino() {
		System.out.println("그린티 크림 프라푸치노를 선택하셨습니다.");
	}

	@Override
	public int cost() {
		System.out.println("그린티 크림 프라푸치노 가격 : 5000");
		return 5000;
	}

}

public abstract class CoffeeDecorator implements StarbucksMenu{

	public abstract int cost();
	
}

스타벅스 메뉴 인터페이스에

기본메뉴인 그린티 크림 프라푸치노와

부가메뉴인 커피데코레이터가 연결되어있다.

 

public class EspressoShot extends CoffeeDecorator{
	
	StarbucksMenu starbucksMenu;

	public EspressoShot(StarbucksMenu starbucksMenu) {
		System.out.println("샷 추가 + 1000원 추가");
		this.starbucksMenu = starbucksMenu;
	}

	@Override
	public int cost() {
		return starbucksMenu.cost() + 1000;
		
	}
}

public class JavaChip extends CoffeeDecorator{
	
	StarbucksMenu starbucksMenu;

	public JavaChip(StarbucksMenu starbucksMenu) {
		System.out.println("자바 칩 +500원 추가");
		this.starbucksMenu = starbucksMenu;
	}

	@Override
	public int cost() {
		return starbucksMenu.cost() + 500;
	}
}

public class LowFatMilk extends CoffeeDecorator{
	
	StarbucksMenu starbucksMenu;

	public LowFatMilk(StarbucksMenu starbucksMenu) {
		System.out.println("저지방 우유 +300원 추가");
		this.starbucksMenu = starbucksMenu;
	}

	@Override
	public int cost() {
		return starbucksMenu.cost() + 300;
	}
}

추상클래스인 커피데코레이터의 구현은

자식클래스인 자바칩, 저지방우유, 에스프레소샷에 구현된다.

 

public class Customer {

	public static void main(String[] args) {
		System.out.println("그린티 프라푸치노에 자바칩, 저지방우유, 샷 추가 해주세요.");
		
		StarbucksMenu order = new EspressoShot(new LowFatMilk(new JavaChip(new GreenTeaCreamFrappuccino())));
		
		System.out.println("총 가격은 " + order.cost() + "입니다.");
	}
}

고객이 위와 같이 주문을 하면

기본 메뉴를 먼저 생성한 후

기본 메뉴에 추가메뉴를 더해 총 가격을 구할 수 있다.

결과 창은 다음과 같다.

 

7. 참고

https://lalwr.blogspot.com/2016/02/decorator-pattern.html

https://secretroute.tistory.com/entry/Head-First-Design-Patterns-%EC%A0%9C3%EA%B0%95-Decorator-%ED%8C%A8%ED%84%B4

https://meaownworld.tistory.com/91

https://meylady.tistory.com/53

https://free-strings.blogspot.com/2016/04/adapter-decorator-facade-proxy.html

https://jusungpark.tistory.com/9

 

Made by 꿩

'스터디 > GoF의 디자인패턴' 카테고리의 다른 글

Chain of Responsibility  (0) 2019.05.06
Strategy Pattern  (0) 2019.04.30
Template Method Pattern  (0) 2019.04.30
Factory Method Pattern  (0) 2019.04.23

#Factory Method Pattern

 

 

1. 개념

 

팩토리 메서드 패턴(Factory method pattern)은 객체를 생성하는 공장을 만드는 것으로서

어떤 객체를 만드는 지는 자식클래스에서 결정하게 하는 디자인 패턴이다.

 

 

2. Why? 왜 사용해야 할까?

 

그렇다면 이 팩토리 메서드 패턴을 왜 사용해야 할까?

한마디로 말하자면

객체 간의 결합도를 낮추고 유지보수를 용이하게 하기 위해서이다.

 

객체만 생성하는 공장을 통해서 간접적으로 객체를 생성하게 하며

인터페이스를 정의하되, 실제 구현내용은 자식클래스에서 구현이 되므로

세부 구현 코드를 몰라도 부모클래스에서 자유롭게 사용이 가능하여

객체 간의 결합도가 낮아지는 효과를 볼 수 있다.

 

객체 간의 결합도가 낮춰진다는 말은

한 클래스에 변화가 생겼을 때 다른 클래스에 영향이 끼치는 정도가 낮아진다는 말이고

유지보수를 할 때 최소의 클래스만 수정이 가능하게 되어

유지보수가 용이하게 되는 결과를 낳는다.

 

3. 장점

 

팩토리 메서드 패턴은

직접 객체를 생성하는 것이 아니라

객체만을 생성하는 공장을 만들어서

객체 생성을 중간 매개체인 공장에서 불러오는 것이다.

객체들은 한 공장에서만 생성되기 때문에

객체들을 한 곳에서 관리할 수 있다는 장점이 있으며

객체의 생명주기를 관리하기 쉬워진다.

 

동일한 인터페이스에서 구현이 되기 때문에

새로운 클래스가 추가되거나 확장하게 되어도

기존 소스코드를 변경할 필요 없이 새로운 하위 클래스를 만들면 되기 때문에

새로운 객체를 생성하는 것보다 유연하고 확장성 있는 구조가 된다.

 

프로그램 내에서 동일한 객체의 호출이 잦고

객체를 생성하는 비용이 클경우

객체를 반복하여 반환하여 사용할 경우 성능을 높일 수 있다.

 

또한,

생성자가 아닌 메소드로 작동하기 때문에 리턴 값을 가질 수 있다.

이는 리턴 값으로 상황에 따라 서로 다른 객체를 반환 할 수 있다는 뜻이다.

객체를 선택함에 있어서 유연함을 가질 수 있는 방법이다.

 

 

4. 단점

 

다만, 팩토리 메서드는 계속해서 새로운 하위클래스를 정의한다는 점이 있다.

이는 불필요하게 많은 클래스를 정의하게 될 수 있고

이로 인해 복잡해 질 수 있다는 단점이 있다.

 

 

5. 클래스 다이어그램

 

 

6. 예제 코드

 

우선, Furniture 인터페이스 하위에 DeskMaker, ChairMaker, BedMaker 하위 클래스가 존재한다.

public interface Furniture {
	
	public void make();
	
	public void newDesign();

}

public class DeskMaker implements Furniture{

	public DeskMaker() {
		System.out.println("책상메이커 삼삼대기");
	}

	@Override
	public void make() {
		System.out.println("책상을 만들었습니다.");
	}
	
	@Override
	public void newDesign() {
		System.out.println("새로운 책상 디자인을 연구합니다.");
		
	}
}

public class ChairMaker implements Furniture{

	public ChairMaker() {
		System.out.println("의자메이커 삼삼대기");
	}
	
	@Override
	public void make() {
		System.out.println("의자를 만들었습니다.");
	}
	
	@Override
	public void newDesign() {
		System.out.println("새로운 의자 디자인을 연구합니다.");
		
	}
}

	public BedMaker() {
		System.out.println("침대메이커 삼삼대기");
	}

	@Override
	public void make() {
		System.out.println("침대를 만들었습니다.");
	}

	@Override
	public void newDesign() {
		System.out.println("새로운 침대 디자인을 연구합니다.");
		
	}
}

 

클라이언트, 즉 Ikea는 각 가구를 생성하기 위해 IkeaFactory를 통해 객체를 불러들인다.

IkeaFactory는 입력받은 값으로 불러올 객체를 구분한다.

public class Ikea {

	public static void main(String[] args) {
		
		IkeaFactory ikeaFactory = new IkeaFactory();
		
		System.out.println("주문 1: 책상 생성");
		ikeaFactory.order("책상").make();
		
		System.out.println("주문 2: 의자 생성");
		ikeaFactory.order("의자").make();
		
		System.out.println("주문 3: 침대 디자인 연구");
		ikeaFactory.order("침대").newDesign();
		
	}

}

public class IkeaFactory {
	
	public Furniture order(String type){
		
		if (type == "침대") {return new BedMaker();}
		if (type == "의자") {return new ChairMaker();}
		if (type == "책상") {return new DeskMaker();}
		
		return null;
		
	}

}

 

main으로 부터 나온 결과값은 다음과 같다.

 

7. 참고

http://egloos.zum.com/ani2life/v/2887675

https://m.blog.naver.com/itperson/220885347418

https://xxxelppa.tistory.com/36

http://egloos.zum.com/sakula99/v/2976589

 

Made by 꿩

'스터디 > GoF의 디자인패턴' 카테고리의 다른 글

Chain of Responsibility  (0) 2019.05.06
Strategy Pattern  (0) 2019.04.30
Template Method Pattern  (0) 2019.04.30
Decorator Pattern  (0) 2019.04.28

+ Recent posts