Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 스테이트패턴
- 상태패턴
- ViewController
- Xcode
- 추상팩토리패턴
- 컴파운드패턴
- 싱글턴패턴
- WKWebView
- 어댑터패턴
- 옵저버패턴
- RxSwift
- 프록시패턴
- 템플릿메서드
- Scenedelegate
- cocoapods
- 팩토리메서드패턴
- 컴포지트패턴
- 파사드패턴
- 이터레이터패턴
- DispatchQueue
- 데코레이터패턴
- 커맨드패턴
- 디자인패턴
- unowned
- ios
- 스트래터지패턴
- Lifecycle
- SWIFT
- Mobile
- 전략패턴
Archives
- Today
- Total
ios dev kangwook.
15. Compound Pattern 본문
Compound Pattern은 두 개 이상의 패턴을 결합해 일반적으로 자주 등장하는 문제들에 대한 해법을 제공
Compound Pattern
- 컴파운드 패턴은 딱히 정해진 의미나 장단점이 뚜렷하지 않음
- 상황에 맞게 서로 다른 패턴을 섞어쓰는 디자인 패턴이기 때문
- 주의할 점은 패턴 몇 개를 결합해서 쓴다고 무조건 컴파운드 패턴이 되는 것이 아님
- 컴파운드 패턴이라 불리기 위해서는 여러 문제를 해결하기 위한 용도로 쓰일 수 있는 일반적인 해결책이어야 함Context : State를 이용하는 역할을 수행
Compound Pattern 예제
- 1장에서 작성했던 Duck 예제의 리팩토링
- Quackable 인터페이스 정의No Quarter : 동전 없음
public interface Quackable{
public void quack();
}
- 완전한 오리는 아니지만 오리의 행동을 할 수 있는 오리 호출기(DuckCall), 모형 오리(RubberDuck)
public class DuckCall implements Quackable {
public void quack() {
System.out.println("kwak");
}
}
public class RubberDuck implements Quackable {
public void quack() {
System.out.println("Squack");
}
}
- 거위 클래스를 추가하고 Duck이 들어가는 곳에 거위도 들어갈 수 있게 하기 : 거위용 어댑터
- 거위는 오리와 다르게 울기 때문에 quack() 메소드 대신 honk() 메소드를 가지고 있음
- 거위용 어댑터를 생성해서 거위를 오리처럼 사용
public class GooseAdapter implements Quackable {
Goose goose;
public GooseAdapter(Goose goose) {
this.goose = goose;
}
//quack()메소드가 호출되면 goose의 honk() 메소드를 호출한다.
public void quack() {
goose.honk();
}
}
- 오리 클래스는 그대로 두면서 오리떼가 꽥꽥한 횟수를 세어보기 : 데코레이터 패턴
- 꽥 소리를 카운트해주는 기능을 추가하기 위한 데코레이터를 만들어 Duck 객체를 감싸기
public class QuackCounter implements Quackable {
Quackable duck;
static int numberOfQuacks;
//모든 객체의 회수를 세야하기 때문에 정적 변수 사용
public QuackCounter (Quackable duck) {
this.duck = duck;
}
public void quack() {
//quack 메소드를 호출하면 데코레이터 안에 있는 duck객체에 위임하고
//numberOfQuacks 를 증가한다.
duck.quack();
numberOfQuacks++;
}
public static int getQuacks() {
return numberOfQuacks;
}
}
- 오리를 생산하기 위한 패턴 : 추상 팩토리 패턴
- 오리를 생성할 때마다 데코레이터로 감싸지 않으면 정확히 카운트를 할 수 없음
- 오리를 생성하는 작업을 한 곳에서 몰아서 하도록 함
public abstract class AbstractDuckFactory {
public abstract Quackable createMallardDuck();
public abstract Quackable createRedheadDuck();
public abstract Quackable createDuckCall();
public abstract Quackable createRubberDuck();
}
//서브클래스 각 메소드에서 다른 종류의 오리를 생성
public class CountingDuckFactory extends AbstractDuckFactory {
public Quackable createMallardDuck() {
return new QuackCounter(new MallardDuck());
}
public Quackable createRedheadDuck() {
return new QuackCounter(new RedheadDuck());
}
public Quackable createDuckCall() {
return new QuackCounter(new DuckCall());
}
public Quackable createRubberDuck() {
return new QuackCounter(new RubberDuck());
}
}
- 오리 무리를 만들어 오리들을 하나로 관리 : 컴포지트 패턴
- Composite : Flock
- Leaf : Quackable
- Composite에만 자식을 관리하기 위한 기능을 넣음
public class Flock implements Quackable {
//ArrayList로 오리떼에 속하는 오리들을 보관함
ArrayList quackers = new ArrayList();
public void add(Quackable quacker) {
quackers.add(quacker);
}
//Flock에 들어있는 모든 오리들의 quack()을 호출해주어야함
public void quack() {
Iterator iterator = quackers.iterator();
while (iterator.hasNext()) {
Quackable quacker = (Quackable)iterator.next();
quacker.quack();
}
}
public String toString() {
return "Flock of Quackers";
}
}
- 실시간으로 꽥꽥거리는 오리들을 각각 추적할 수 있는 기능 추가 : 옵저버 패턴
- Observable 인터페이스 추가
public interface QuackObservable {
//Observer 인터페이스를 구현하는 객체라면 어떤 객체는 꽥꽥거리는걸 감시할 수 있음
public void registerObserver(Observer observer);
public void notifyObservers();
}
- Quackable에서 QuackObservable 인터페이스를 상속
- Quackable을 구현하는 모든 Concrete class에서 QuackObservable도 구현하도록 해야함
public class Observable implements QuackObservable {
ArrayList observers = new ArrayList();
QuackObservable duck;
public Observable(QuackObservable duck) {
this.duck = duck;
}
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers() {
Iterator iterator = observers.iterator();
while (iterator.hasNext()) {
Observer observer = (Observer)iterator.next();
observer.update(duck);
}
}
public Iterator getObservers() {
return observers.iterator();
}
}
- 각 오리 클래스에서 Observable 객체를 가지고 있고 QuackObservable과 관련된 모든 기능을 해당 객체에 위임
public class RubbserDuck implements Quackable {
Observable observable;
public MallardDuck() {
observable = new Observable(this);
}
public void quack() {
System.out.println("Squack");
notifyObservers();
}
//QuackObservable에서 정의한 메소드들
//모두 observable 보조 객체에 작업을 위임한다.
public void registerObserver(Observer observer) {
observable.registerObserver(observer);
}
public void notifyObservers() {
observable.notifyObservers();
}
public String toString() {
return "Rubber Duck";
}
}
- 마지막으로 옵저버쪽 코드를 작성
public interface Observer {
//꽥소리를 낸 오리를 인자로 받는 메소드
public void update(QuackObservable duck);
}
//꽥학자 클래스
public class Quackologist implements Observer {
public void update(QuackObservable duck) {
System.out.println("Quackologist: " + duck + " just quacked.");
}
}
패턴은 반드시 상황에 맞게 사용해야 한다!
본문은 Head First Design Pattern (2004) 를 참고하여 공부하고 작성하였음
'Design Pattern' 카테고리의 다른 글
14. Proxy Pattern (0) | 2022.09.06 |
---|---|
13. State Pattern (0) | 2022.09.05 |
12. Composite Pattern (0) | 2022.09.04 |
11. Iterator Pattern (0) | 2022.08.31 |
10. Template Method Pattern (0) | 2022.08.29 |
Comments