'프로그래밍 > 디자인패턴' 카테고리의 다른 글
디자인패턴요약 (0) | 2018.06.11 |
---|---|
디자인 패턴 요약 (0) | 2018.06.11 |
쉽게 배우는 Template 패턴 (0) | 2017.01.29 |
쉽게 배우는 Builder 패턴 (0) | 2017.01.29 |
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
디자인패턴요약 (0) | 2018.06.11 |
---|---|
디자인 패턴 요약 (0) | 2018.06.11 |
쉽게 배우는 Template 패턴 (0) | 2017.01.29 |
쉽게 배우는 Builder 패턴 (0) | 2017.01.29 |
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
GoF(Gang of Four)에서는 23가지 디자인 패턴을 3가지 유형으로 분류합니다.
주요 디자인 패턴만 정리했습니다.
Class Diagram
구현 및 Code
public interface Observer { public abstract void update(NumberGenerator generator); }
import java.util.Vector; import java.util.Iterator; public abstract class NumberGenerator { private Vector observers = new Vector(); // Observer들을 보관 public void addObserver(Observer observer) { // Observer를 추가 observers.add(observer); } public void deleteObserver(Observer observer) { // Observer를 삭제 observers.remove(observer); } public void notifyObservers() { // Observer에 통지 Iterator it = observers.iterator(); while (it.hasNext()) { Observer o = (Observer) it.next(); o.update(this); } } public abstract int getNumber(); // 수를 취득한다. public abstract void execute(); // 수를 생성한다. }
import java.util.Random; public class RandomNumberGenerator extends NumberGenerator { private Random random = new Random(); // 난수발생기 private int number; // 현재의 수 public int getNumber() { // 수를 취득한다. return number; } public void execute() { for (int i = 0; i < 20; i++) { number = random.nextInt(50); notifyObservers(); } } }
public class DigitObserver implements Observer { public void update(NumberGenerator generator) { System.out.println("DigitObserver:" + generator.getNumber()); try { Thread.sleep(100); } catch (InterruptedException e) { } } }
public class GraphObserver implements Observer { public void update(NumberGenerator generator) { System.out.print("GraphObserver:"); int count = generator.getNumber(); for (int i = 0; i < count; i++) { System.out.print("*"); } System.out.println(""); try { Thread.sleep(100); } catch (InterruptedException e) { } } }
public class Main { public static void main(String[] args) { NumberGenerator generator = new RandomNumberGenerator(); Observer observer1 = new DigitObserver(); Observer observer2 = new GraphObserver(); generator.addObserver(observer1); generator.addObserver(observer2); generator.execute(); } }
디자인패턴 요약 (0) | 2018.06.11 |
---|---|
디자인 패턴 요약 (0) | 2018.06.11 |
쉽게 배우는 Template 패턴 (0) | 2017.01.29 |
쉽게 배우는 Builder 패턴 (0) | 2017.01.29 |
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
말하자면 구조적인 문제를 해결하는 방식을 이름을 붙여서 재이용하기 좋은 형태로 정리해둔 것이죠.
오늘 알아볼 GoF의 디자인 패턴은 위에도 있다시피 네명의 컴퓨터과학 연구자들이 소개한 대표적인 디자인패턴 방식입니다.
물론 아 대충 이런것이구나 는 이해가 금방될지라도 실제로 프로그래밍에 사용하려면 어려운점이 많아짐으로
우선 대략적으로 설명을 해두고 나중에 하나씩 따로 포스팅하도록 하겠습니다.
디자인패턴 요약 (0) | 2018.06.11 |
---|---|
디자인패턴요약 (0) | 2018.06.11 |
쉽게 배우는 Template 패턴 (0) | 2017.01.29 |
쉽게 배우는 Builder 패턴 (0) | 2017.01.29 |
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
전체적인 로직에는 큰 차이가 없지만 일부분만 바뀌는 비스무레한 몇 가지 클래스가 있다고 칩시다. 일부분을 위해서 전체를 새로 작성할 필요는 없지요. Template Method에서는 전반적인 구현은 상위클래스(주로 Abstract로 만듭니다.)에서 담당하고 부분적인 곳의 구체적인 구현은 하위클래스가 담당합니다.
2. 예제
------------- 템플릿 메쏘드가 있는 Abstract Class ---------------
package ch04_TemplateMethod;
public abstract class Worker {
protected abstract void doit();
public final void work(){
System.out.println("출근");
doit();
System.out.println("퇴근");
}
}
------------- Abstract Class 구현체 1 ---------------------
package ch04_TemplateMethod;
public class Designer extends Worker {
@Override
protected void doit() {
System.out.println("열심히 디자인");
}
}
------------- Abstract Class 구현체 2 ---------------------
package ch04_TemplateMethod;
public class Gamer extends Worker {
@Override
protected void doit(){
System.out.println("열심히 껨질");
}
}
------------- 테스트 코드 ---------------------
package ch04_TemplateMethod;
public class Test {
public static void main(String[] args) {
Worker designer = new Designer();
designer.work();
Worker gamer = new Gamer();
gamer.work();
}
}
Worker 클래스의 work()는 내부적으로 abstract 메쏘드인 doit()을 호출하고 있습니다. work() 안에서 전반적인 로직이 수행되고, 로직 중 각각의 특성을 탈 수 있는 부분을 doit() 안에서 해결합니다. doit()은 실제 구현체에서 알아서 구현하면 됩니다.
work() 를 final로 구현한 것은 하위 클래스에서 전체적인 로직 변경을 하지 못하도록 하는 것입니다.
3. Template Method 사용시 고려사항
Template Method는 위험성을 어느 정도 내포하고 있습니다. 바로 전체적인 프로세스가 바뀌는 것입니다. 상위 클래스에서 변동이 일어날 경우 하위 클래스가 안전하리라는 보장은 할 수 없습니다. 상위 클래스에 abstract method가 하나만 추가되어도 모든 하위 클래스는 변경이 불가피합니다. 나중에 발생하는 작은 변경이 큰 재난을 일으킬 수 있습니다. 이것은 상속이 가지는 위험성입니다.
그래서 Template Method 패턴을 사용할 때는 상위클래스에 대한 심사숙고가 반드시 필요합니다. 일반적으로는 전체적인 프로세스를 담당하는 로직을 final 메쏘드로 정의하기도 하지만, 프로세스 자체의 변경을 고려해 상속의 여지를 남겨두기 위해 final 메쏘드로 정의하지 않기도 합니다.
또 한가지는 하위 클래스의 메쏘드들은 외부에서 직접 호출되지 않고 상위 클래스의 Template Method에서 호출됩니다. 그래서 주로 protected 로 선언됩니다. 그런 이유로 외부의 호출과 구체적인 구현체의 메쏘드가 실행되기까지의 과정을 쉽게 파악하기가 어렵습니다. 문제가 생겼을 때 추적이 어려울 수도 있다는 것이죠.
4. JAVA API에 있는 Template Method
아마 JDK안에 가장 많이 들어 있는 패턴 중 하나가 Template Method일 겁니다.
Servlet 을 개발할 때, HttpServlet을 상속 받아 doGet() 과 doPost() 를 구현합니다. HttpServlet의 service() 에서 하위구현체의 doGet()이나 doPost() 등으로 분기를 시킵니다.(그 외에도 do머시기하는 메쏘드가 있지만 생략합니다.) Template Method의 전형적인 사용법 중 하나입니다. 분기를 담당하는 부분은 상위클래스에 구체적으로 구현하고, 분기된 이후의 행동은 하위구현체에 떠 넘기는 방법이죠.
HashSet이라는 Set의 구현체를 아시죠? 얘는 Set이니까 중복 데이터를 요소로 가지지 않습니다. 그럼 '같다 다르다'의 기준은 뭘까요? 내용이 같으면 될까요? 아니면, 실제 레퍼런스가 같아야 할까요?
이름에 나와 있듯 hash 값이 일단 같아야 합니다. hash값은 Object의 hashCode() 메쏘드를 이용하여 체크합니다. 그리고 나서 또 Object의 equals() 메쏘드를 호출합니다. 그래서 Set에 넣을 요소에 대해서는 hashCode() 메쏘드와 equals() 메쏘드가 잘 구현되어있어야 합니다. 그렇지 않으면, 중복된 데이터가 삽입될 수 있습니다.
HashSet의 경우는 위에서 설명한 Template Method와는 좀 다릅니다. 상위클래스와 하위클래스의 상관관계 같은 게 없죠. 다만 나도 모르는 사이에 내가 구현한 메쏘드가 호출될 수 있기 때문에 Template Method가 될 수 있습니다.(HashSet의 add(SomeClass) 메쏘드는 SomeClass의 hashCode()와 equals()를 호출합니다. )
정확히 말하면 Set.add(SomeClass) 메쏘드는 Set.contains(SomeClass) 메쏘드를 호출하고 그 안에서 다시 SomeClass.hashCode()와 SomeClass.equals(SomeClass) 를 호출합니다. ( 중간에 좀 더 복잡한 과정이 있지만, 설명할 필요는 없으므로 생략합니다. )
여기서 UI관련 각종 EventListener들도 그런 맥락에서 Template Method라고 볼 수 있습니다. event 발생에서 리스너까지의 과정을 알 필요가 없습니다. 대략 어떤 이벤트를 발생시키면, 어떤 이벤트 리스너한테 전달된다 정도만 알면 되죠. 이벤트 핸들링에는 그 외에도 여러가지 패턴들이 적용되어 있습니다.
디자인패턴요약 (0) | 2018.06.11 |
---|---|
디자인 패턴 요약 (0) | 2018.06.11 |
쉽게 배우는 Builder 패턴 (0) | 2017.01.29 |
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
쉽게 배우는 Iterator 패턴 (이터레이터 패턴) (0) | 2017.01.29 |
1. Builder 패턴이란?
bulider pattern은 창조적 디자인 패턴(creational patter) 에 속합니다. 이것은 factory pattern 또는 abstract factory pattern과 매우 비슷합니다.
2. 예제
3. 자바에서 쓰이는 builder 패턴
java.lang.StringBuilder
은 대표적인 빌더 패턴이라고 볼수 있습니다.
시간이 되실때 소스를 보시면 많은 도움이 될것입니다.
디자인 패턴 요약 (0) | 2018.06.11 |
---|---|
쉽게 배우는 Template 패턴 (0) | 2017.01.29 |
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
쉽게 배우는 Iterator 패턴 (이터레이터 패턴) (0) | 2017.01.29 |
쉽게 배우는 Factory 패턴 (팩토리 패턴) (0) | 2017.01.28 |
1. Adapter 패턴이란
이미 구현되어 있는 코드가 있는데, 둘이 연결 좀 시켜주고 싶을 때가 있죠. 어떤 좋은 메서드가 있는데, 인자로 A라는 형식을 받습니다. 근데, 이미 구현되어 있는 코드에는 B라는 형식으로 구현되어 있습니다. 이럴 때, B를 A의 형식으로 바꿔주면 좋은 메서드를 써먹을 수 있습니다. Adapter 패턴은 어떤 오브젝트를 캐스팅이 불가능한 다른 클래스의 형태로 변환시켜주는 것입니다.
2. 따라하기
// Adapter Class
//test 클래스
우리가 최종적으로 쓰고자하는 것은 nextObject() 입니다. 그 녀석은 인자로 Enumeration을 받고 있지요.
그러나 우리가 가지고 있는 것은 Iterator입니다. IteratorToEnumeration 클래스는 Iterator를 받아서 Enumeration 으로 변경시켜줍니다.
A to B의 형태를 가지는 Adapter는 A를 멤버변수로 가지고 B를 구현합니다.
즉, IteratorToEnumeration 클래스가 이 역활을 하고 있습니다. IteratorToEnumeration 이클래스가 아답터 클래스 입니다.
3. JAVA API에 있는 Adapter 패턴 을 이용한 클래스들
java.util.Arrays#asList()
java.util.Collections#list()
java.util.Collections#enumeration()
java.io.InputStreamReader(InputStream)
(returns a Reader
)java.io.OutputStreamWriter(OutputStream)
(returns a Writer
)javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
and #unmarshal()
쉽게 배우는 Template 패턴 (0) | 2017.01.29 |
---|---|
쉽게 배우는 Builder 패턴 (0) | 2017.01.29 |
쉽게 배우는 Iterator 패턴 (이터레이터 패턴) (0) | 2017.01.29 |
쉽게 배우는 Factory 패턴 (팩토리 패턴) (0) | 2017.01.28 |
디자인 패턴의 간략한 암기 (0) | 2017.01.21 |
1. iterator 패턴이란
개발을 하면서 array나 List, Set, Map과 같은 interface 들을 많이 사용합니다. 이것들의 특징은 어떤 데이터들의 집합체라는 겁니다.
원래 집합체란 게 속에 뭐가 들었냐가 중요하죠.
그래서 집합체들을 다룰 때는 얘들이 가지고 있는 개별 원소에 대해서 이런 저런 작업들을 할 일이 많습니다.
iterator를 쓰게 되면, 집합체와 개별 원소들간에 분리시켜 생각할 수가 있습니다. 심지어는 그 집합체가 어떤 클래스의 인스턴스인지 조차 신경쓰지 않아도 됩니다.
2. 예제
// iterator 인터페이스를 만든다.3. Iterator관련 interface
iterator 인터페이스를 만드는 대신에 구현되어 있는 java 의 iterable 인터페이스를 사용해도 됩니다.
private class NameIterator implements Iterable<String> {
위와같은 식으로 구현되어 있는걸 사용해도 되지만 iterator 패턴이 어떤건지 알기 위하여 구현을 임의로 한것입니다.
4. JAVA API에 있는 Iterator
우리가 알고 있는 일반적인 집합체들은 전부 Iterator를 제공합니다. Set, List 등은 Collection 을 상속 받는데, Collection이 Iteratable을 상속 받기 때문입니다.
위에서 청록색 부분을 list.iterator() 라고 쭐여버려도 됩니다. 걍 있는 거 안 쓰고 굳이 구현한 건 예제 파일을 함 보여줄라고 한 겁니다. 사실은 예제 전체가 억지로 만들어낸 겁니다. 일반적인 집합체를 구현해서 쓰는 일은 거의 없고, JDK 안에 들어 있는 애들을 가져다 쓰는데, 걔들은 거의 대부분 Iterator를 제공하거든요.(Map은 한 다리 건너서 제공합니다.) 그래서 Iterator를 직접 구현할 일은 거의 없습니다. 가져다가 쓸 일이 있을 뿐이죠.
이제 Map은 왜 Iterator를 제공하지 않는 지를 살펴보죠. Map은 Set이나 List와는 달리 key-value의 구조입니다. key에 대한 Iterator인지 value에 대한 Iterator인지 구별할 방법이 없죠. 그래서 아예 제공을 안 합니다. 그러나 Map에는 key에 대해서는 Set<K> keySet()이라는 key를 Set으로 가져오기를 지원하고, value에 대해서는 Collection<V> values() 를 제공합니다. 위에서 말씀드렸다시피 Set과 Collection은 둘다 Iterator를 제공합니다.
쉽게 배우는 Builder 패턴 (0) | 2017.01.29 |
---|---|
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
쉽게 배우는 Factory 패턴 (팩토리 패턴) (0) | 2017.01.28 |
디자인 패턴의 간략한 암기 (0) | 2017.01.21 |
factory pattern vs abstract pattern (0) | 2016.09.01 |
1. Factory 패턴 이란
아주 중요한 패턴중에 하나 입니다. Factory 패턴은 creational pattern 에 속하는 패턴입니다.
Factory 패턴은 객체생성로직 없이 객체를 만들어 내는 패턴입니다.. 인터페이스를 통해 만들어진 객체를 참조 하죠.
쉽게 설명해드리겠습니다. factory 는 한국어로 공장이란 뜻이죠. 즉 객체를 만들어내는 공장 입니다.
객체 선언은 보통 new 객체() 이런식으로 하죠. factory는 내부에서 그런 일을 해줍니다. 즉 factory를 가져다가 쓰는 부분에서는 new 객체()와 같은 식으로 변수를 선언할 필요가 없습니다. Abstract class나 인터페이스에 대해서 다양한 하위 구현체가 있을 경우에 사용하면 좋습니다. 사용법은 Factory.create(인자는 맘대로) 와 같이 됩니다.
실무에서 자주 쓰이는 패턴중 하나이니 아래와 같이 천천히 따라해보도록 하죠.
2. 따라하기
// animal 인터페이스를 만듭니다. 기본이 되는 interface 죠. 모든 디자인 패턴은 interface 를 사용한다 해도 과언이 아닙니다.
// Cat 클래스를 만듭니다.
// Cow 클래스를 만듭니다.
// Dog 클래스를 만듭니다.
// animal 을 만들어내는 AnimalFactory 클래스를 만든다.
//( 이 class 가 핵심 입니다. factory 패턴을 구현한곳이죠. 이해하기 힘드시다면 이 class 만 30번 보시면 이해가 되실겁니다.)
// 자 테스트를 한번 해볼까요.
3. Factory 의 이해
위의 결과와 같이 Animal interface 를 이용해서 각자 다른 소리를 내는 3개의 클래스를 만들어 봤습니다.
AnimalFactory 클래스에서는 각 동물들의 이름을 받아서 클래스를 만들어 냈습니다. 즉 팩토리 패턴을 구현해 놓은 클래스 입니다.
테스트를 실행하는 main 클래스 안에는 new 라는 구문 자체가 없습니다 팩토리 패턴은. 정확히 어떤 클래스의 인스턴스인지 신경쓰지 않고 구현할 수 있는 장점이 있습니다. 객체 타입이 굉장히 유연해 질 수 있죠.
이것으로 아주 쉽게 배우는 factory 패턴을 마치고자 합니다.
쉽게 배우는 Adapter 패턴 (아답터 패턴) (0) | 2017.01.29 |
---|---|
쉽게 배우는 Iterator 패턴 (이터레이터 패턴) (0) | 2017.01.29 |
디자인 패턴의 간략한 암기 (0) | 2017.01.21 |
factory pattern vs abstract pattern (0) | 2016.09.01 |
자바 에서 쓰이는 디자인 패턴들 (0) | 2016.08.26 |
수많은 디자인 패턴을 다 익히려면 시간이 많이 걸립니다. 혹은 공부한 디자인 패턴을 잊어버리곤 하죠
요점만 딱 암기 하고 있으면 다음에 디자인 패턴을 쓰고 싶을대 그 요점을 기준으로 다시 생각이 나게끔 아래와 같이 정리를 해봤습니다.
하위클래스에게 위임하기 |
1. Iterator : 순서대로 지정해서 처리하기 2. Adapter : 바꿔서 재이용하기 3. Template Method : 하위 클래스에서 구체적으로 처리하기 4. Factory Method : 하위 클래스에서 인스턴스 만들기 |
인스턴스 만들기 |
5. Singleton : 인스턴스를 한 개만 만들기 6. Prototype : 복사해서 인스턴스 만들기 7. Builder : 복잡한 인스턴스 조립하기 8. Abstract Factory : 관련 부품을 조합해서 제품 만들기 |
분리해서 생각하기 |
9. Bridge : 기능계층과 구현 계층 분리하기 10. Strategy : 알고리즘을 모두 바꾸기 |
동일시 하기 |
11. Composite : 그릇과 내용물을 동일시 하기 12. Decorator : 장식과 내용물을 동일시 하기 |
구조를 돌아다니기 |
13. Visitor : 데이터 구조를 돌아다니면서 처리하기 14. Chain of Responsibility 책임 떠넘기기 |
단순화하기 |
15. Facade : 단순한 창구 16. Mediator : 중개인을 통해서 처리하기 |
상태를 관리하기 |
17. Observer : 상태의 변화를 알려주기 18. Memento : 상태를 저장하기 19. State : 상태를 클래스로 표현하기 |
낭비 없애기 |
20. Flyweight : 동일한 것을 공유해서 낭비 없애기 21. Proxy : 필요해지면 만들기 |
클래스로 표현하기 |
22. Comman : 명령을 클래스로 하기 23. Interpreter : 문법규칙을 클래스로 표현하기 |
쉽게 배우는 Iterator 패턴 (이터레이터 패턴) (0) | 2017.01.29 |
---|---|
쉽게 배우는 Factory 패턴 (팩토리 패턴) (0) | 2017.01.28 |
factory pattern vs abstract pattern (0) | 2016.09.01 |
자바 에서 쓰이는 디자인 패턴들 (0) | 2016.08.26 |
디자인 패턴 기반 웹 어플리케이션 (0) | 2016.08.22 |
쉽게 배우는 Iterator 패턴 (이터레이터 패턴) (0) | 2017.01.29 |
---|---|
쉽게 배우는 Factory 패턴 (팩토리 패턴) (0) | 2017.01.28 |
디자인 패턴의 간략한 암기 (0) | 2017.01.21 |
자바 에서 쓰이는 디자인 패턴들 (0) | 2016.08.26 |
디자인 패턴 기반 웹 어플리케이션 (0) | 2016.08.22 |