12. 컴파운드 패턴

  1. 12. 컴파운드 패턴
    1. 1. 패턴 섞어 쓰기
    2. 2. 모델-뷰-컨트롤러와의 만남(MVC)
    3. 3. MVC 와 웹환경
    4. 문서에 대하여

1. 패턴 섞어 쓰기

1.1 컴파운드 패턴

  • 컴파운드 패턴이란 반복적으로 생길 수 있는 문제를 해결하기 위한 용도로 두 개 이상의 패턴을 결합하여 사용하는 것을 뜻함

1.2 오리와의 재회

1.2.1 오리에 적용될 패턴

  • 1. 처음에 수많은 Quackable 들이 존재
  • 2. 갑자가 거위가 나타나서는 자기도 Quackable이 되고 싶다고함 (어댑터 패턴)
  • 3. 꽥학자들이 등장해서 꽥소리 회수를 세고 싶다고함 (데코레이터 패턴)
  • 4. 꽥학자들이 QuackCounter로 장식되지 않은 Quackable 객체가 있을것을 걱정 (추상팩토리 패턴)
  • 5. 모든 오리와 거위, Quackable 객체들을 관리하는 게 힘들어지기 시작 - 오리떼로 관리 (컴포지트 패턴)
  • 6. 꽥학자들은 Quackable에서 꽥소리를 냈을 때 그런 일이 있었다는 것을 연락받고 싶어함 (옵저버 패턴)

1.2.2 오리가 본 조감도

1.2.3 오리와의 재회

수많은 Quackable 들이 존재거위가 나타나서는 자기도 Quackable이 되고 싶다고함
{code:java}
//==============================================
// 1. 우선 Quackable 인터페이스를 만듭니다.
//==============================================
public insterface Quackable{
public void quack();
}
{code}{code:java}
//==============================================
// 2. Quackable 을 구현해서 오리 클래스를 만듭니다.
//==============================================
public class MallardDuck implements Quackable{
public void quack(){
System.out.println("Quack");
}
}

public class RedheadDuck implements Quackable{
public void quack(){
System.out.println("Quack");
}
}

public class DuckCall implements Quackable{
public void quack(){
System.out.println("Quack");
}
}

public class RubberDuck implements Quackable{
public void quack(){
System.out.println("Quack");
}
}

{code:java}
//==============================================
// 3. 시뮬레이터 생성
//==============================================
public class DuckSimulator{
   public static void main(String[] args){
      DuckSimulator simulator = new DuckSimulator();
      simulator.simulate();
   }

   void simulate(){
      Quackable mallardDuck = new MallardDuck();
      Quackable redheadDuck= new RedheadDuck();
      Quackable duckCall = new DuckCall();
      Quackable rubberDuck = new RubberDuck();

      System.out.println("\nDuck Simulator");

      simulate(mallardDuck);
      simulate(redheadDuck);
      simulate(duckCall);
      simulate(rubberDuck);
   }

   void simulate(Quackable duck){
      duck.quack();
   }
}

|


//==============================================
// 4. 오리 있는곳에 거위도 있다.
//==============================================
public class Goose{
   public void honk();{
      System.out.println("Honk");
   }
}


//==============================================
// 5. 거위용 어댑터 필요
//==============================================
public class GooseAdapter implements Quackable{
   Goose goose;

   public GooseAdapter(Goose goose){
      this.goose = goose;
   }

   public void quack(){
      goose.honk();
   }
}


//==============================================
// 5. 거위를 추가한 시뮬레이터
//==============================================
public class DuckSimulator{
   public static void main(String[] args){
      DuckSimulator simulator = new DuckSimulator();
      simulator.simulate();
   }

   void simulate(){
      Quackable mallardDuck = new MallardDuck();
      Quackable redheadDuck= new RedheadDuck();
      Quackable duckCall = new DuckCall();
      Quackable rubberDuck = new RubberDuck();
      Quackable gooseDuck = new GooseAdapter(new Goose());

      System.out.println("\nDuck Simulator : With Goose Adapter");

      simulate(mallardDuck);
      simulate(redheadDuck);
      simulate(duckCall);
      simulate(rubberDuck);
      simulate(gooseDuck);
   }

   void simulate(Quackable duck){
      duck.quack();
   }
}

|

꽥소리 회수를 세고 싶다고함QuackCounter로 장식되지 않은 Quackable 객체가 있을것을 걱정
{code:java}
//==============================================
// 6. 꽥소리를 낸 회수를 세 주는 기능 선물
//==============================================
public class QuackCounter implements Quackable{
Quackable duck;
static int numberOfQuacks;

public void QuackCounter(Quackable duck){
duck.quack();
numberOfQuacks++;
}

public static int getQuack(){
return numberOfQuacks;
}
}

{code:java}
//==============================================
// 7. 모든 오리들을 데코레이터로 감싸줍니다.
//==============================================
public class DuckSimulator{
   public static void main(String[] args){
      DuckSimulator simulator = new DuckSimulator();
      simulator.simulate();
   }

   void simulate(){
      Quackable mallardDuck = new QuackCounter(new MallardDuck());
      Quackable redheadDuck= new QuackCounter(new RedheadDuck());
      Quackable duckCall = new QuackCounter(new DuckCall());
      Quackable rubberDuck = new QuackCounter(new RubberDuck());
      Quackable gooseDuck = new GooseAdapter(new Goose());

      System.out.println("\nDuck Simulator : With Decorator");

      simulate(mallardDuck);
      simulate(redheadDuck);
      simulate(duckCall);
      simulate(rubberDuck);
      simulate(gooseDuck);

      System.out.println("The ducks quacked "+QuackCounter.getQuacks()
                     + " times");
   }

   void simulate(Quackable duck){
      duck.quack();
   }
}

|


//==============================================
// 8. 오리를 생산하기 위한 팩토리가 필요
//==============================================
public abstract class AbstractDuckFactory{

   public abstract Quackable createMallardDuck();
   public abstract Quackable createRedheadDuck();
   public abstract Quackable createDuckCall();
   public abstract Quackable createRubberDuck();
}


//==============================================
// 9. 데코레이터가 없는 Factory 와 진짜로 사용할 CountingDuckFactory
//==============================================
public class DuckFactory extends AbstractDuckFactory{

   public Quackable createMallardDuck(){
      return new MallardDuck();
   }

   public Quackable createRedheadDuck(){
      return new ReadheadDuck();
   }

   public Quackable createDuckCall(){
      return new DuckCall();
   }

   public Quackable createRubberDuck(){
      return new RubberDuck();
   }
}

public class CountingDuckFactory extends AbstractDuckFactory{

   public Quackable createMallardDuck(){
      return QuackCounter(new MallardDuck());
   }

   public Quackable createRedheadDuck(){
      return QuackCounter(new ReadheadDuck());
   }

   public Quackable createDuckCall(){
      return QuackCounter(new DuckCall());
   }

   public Quackable createRubberDuck(){
      return QuackCounter(new RubberDuck());
   }
}


//==============================================
// 10. 팩토리를 사용하도록 시뮬레이터 수정
//==============================================
public class DuckSimulator{
   public static void main(String[] args){
      DuckSimulator simulator = new DuckSimulator();
      AbstractDuckFactory duckFactory = new CountingDuckFactory();

      simulator.simulate(duckFactory);
   }

   void simulate(AbstractDuckFactory duckFactory){
      Quackable mallardDuck = duckFactory.createMallardDuck();
      Quackable redheadDuck= duckFactory.createReadheadDuck();
      Quackable duckCall = duckFactory.createDuckCall();
      Quackable rubberDuck = duckFactory.createRubberDuck();
      Quackable gooseDuck = new GooseAdapter(new Goose());

      System.out.println("\nDuck Simulator : With Decorator");

      simulate(mallardDuck);
      simulate(redheadDuck);
      simulate(duckCall);
      simulate(rubberDuck);
      simulate(gooseDuck);

      System.out.println("The ducks quacked "+QuackCounter.getQuacks()
                       + " times");
   }

   void simulate(Quackable duck){
      duck.quack();
   }
}

|

오리떼로 관리꽥소리를 냈을 때 그런 일이 있었다는 것을 연락받고 싶어함
{code:java}
//==============================================
// 11. 오리떼를 만들어 봅니다.
//==============================================
public class Flock implements Quackable{
ArrayList quackers = new ArrayList();

public void add(Quackable quacker){
quacker.add(quacker);
}

public void quack(){
Iterator iterator = quacker.iterator();
while(iterator.hasNext()){
Quackable quacker = (Quackable)iterator.next();
quacker.quack();
}
}
}

{code:java}
//==============================================
// 12. 시뮬레이터를 수정
//==============================================
public class DuckSimulator{
   public static void main(String[] args){
      DuckSimulator simulator = new DuckSimulator();
      AbstractDuckFactory duckFactory = new CountingDuckFactory();

      simulator.simulate(duckFactory);
   }

   void simulate(AbstractDuckFactory duckFactory){

      Quackable redheadDuck= duckFactory.createReadheadDuck();
      Quackable duckCall = duckFactory.createDuckCall();
      Quackable rubberDuck = duckFactory.createRubberDuck();
      Quackable gooseDuck = new GooseAdapter(new Goose());

      System.out.println("\nDuck Simulator : With Composite-Flocks");

      Flock flockOfDucks = new Flock();

      flockOfDucks.add(redheadDuck);
      flockOfDucks.add(duckCall);
      flockOfDucks.add(rubberDuck);
      flockOfDucks.add(gooseDuck);

      Flock flockOfMallards = new Flock();

      Quackable mallardOne = duckFactory.createMallardDuck();
      Quackable mallardTwo = duckFactory.createMallardDuck();
      Quackable mallardThree = duckFactory.createMallardDuck();
      Quackable mallardFour = duckFactory.createMallardDuck();

      flockOfMallards.add(mallardOne);
      flockOfMallards.add(mallardTwo);
      flockOfMallards.add(mallardThree);
      flockOfMallards.add(mallardFour);

      flockOfDucks.add(flockOfMallards);

      System.out.println("\nDuck Simulator : Whole Flock Simulator");
      simulate(flockOfDucks);

      System.out.println("\nDuck Simulator : Mallard Flock Simulator");
      simulate(flockOfMallards);

      System.out.println("The ducks quacked "+QuackCounter.getQuacks()
                       + " times");
   }

   void simulate(Quackable duck){
      duck.quack();
   }
}

|


//==============================================
// 13. Observable 인터페이스 필요
//==============================================
public interface QuackObservable{
   public void registerObserver(Observer observer);
   public void notifyObservers();
}

public interface Quackable extends QuackObservable{
   public void quack();
}


//==============================================
// 14. 메소드 구현
//==============================================
public class Observable implements QuackObservable{
   ArrayList observers = new ArrayList();
   QuackObservable duck;

   public Observable(QuackObservable duck){
      this.duck = duck;
   }

   public void reigisterObserver(Observer observer){
      observers.add(observer);
   }

   public void notifyObservers(){
      Iterator iterator = observers.iterator();
      while(iterator.hasNext()){
         Observer observer = (Observer)iterator.next();
         observer.update(duck);
      }
   }
}


//==============================================
// 15. Observer 보조객체와 Quackable 클래스를 결합
//==============================================
public class MallardDuck implements Quackable{
   Observable observable;

   public MallardDuck(){
      observable = new Observable(this);
   }

   public void quack(){
      System.out.println("Quack");
      notifyObservers();
   }

   public void registerObserver(Observer observer){
      observable.registerObserver(observer)
   }

   public void notifyObservers(){
      observable.notifyObservers();
   }
}


//==============================================
// 16. 옵저버 패턴의 옵저버 쪽 완성
//==============================================
public interface Observer{
   public void update(QuackObservable duck);
}

public class Quackologist implements Observer{

   System.out.println("Quackologist:+duck+" just quacked.");
}


//==============================================
// 17. 시뮬레이터 수정
//==============================================
public class DuckSimulator{
   public static void main(String[] args){
      DuckSimulator simulator = new DuckSimulator();
      AbstractDuckFactory duckFactory = new CountingDuckFactory();

      simulator.simulate(duckFactory);
   }

   void simulate(AbstractDuckFactory duckFactory){

      Quackable redheadDuck= duckFactory.createReadheadDuck();
      Quackable duckCall = duckFactory.createDuckCall();
      Quackable rubberDuck = duckFactory.createRubberDuck();
      Quackable gooseDuck = new GooseAdapter(new Goose());

      System.out.println("\nDuck Simulator : With Composite-Flocks");

      Flock flockOfDucks = new Flock();

      flockOfDucks.add(redheadDuck);
      flockOfDucks.add(duckCall);
      flockOfDucks.add(rubberDuck);
      flockOfDucks.add(gooseDuck);

      System.out.println("\nDuck Simulator : With Observer");
      Quackologist quackologist = new Quackologist();
      flockOfDucks.registerObserver(quackologist);

      System.out.println("\nDuck Simulator : Whole Flock Simulator");
      simulate(flockOfDucks);

      System.out.println("The ducks quacked "+QuackCounter.getQuacks()
                       + " times");
   }

   void simulate(Quackable duck){
      duck.quack();
   }
}

|

2. 모델-뷰-컨트롤러와의 만남(MVC)

2.1 모델-뷰-컨트롤러와의 만남

  • 모델에서는 옵저버 패턴을 사용하여 상태가 바뀔 때마다 뷰와 컨트롤러한테 연락을 함
  • 뷰와 컨트롤러에서는 스트래티지 패턴을 사용 : 컨트롤러는 뷰의 행동에 해당하며, 다른 행동을 원하면 다른 컨틀롤러로 교체하면 된다
  • 뷰 안에서는 내부적으로 컴포진트 패턴을 사용

2.2 옵저버 패턴

2.3 스트래티지 패턴

2.4 컴포지트 패턴

3. MVC 와 웹환경

3.1 MVC 와 웹환경

  • 1. 사용자가 HTTP요청을 하면 서블릿에서 그 요청을 수신
  • 2. 서블릿이 컨트롤 역할을 합니다.
  • 3. 컨트롤러에서는 컨트롤을 뷰한테 넘깁니다.
  • 4. 뷰에서 HTTP를 통해서 브라우저한테 페이지를 전달합니다.

3.2 모델2

모델2는 MVC를 웹에 맞게 적용모델
{code:java}
//==============================================
// 1. BeatModel Interface
//==============================================
public interface BeatModelInterface{
void initialize();

void on();

void off();

void setBPM(int bpm);

int getBPM();

void registerObserver(BeatObserver o);

void removeObserver(BeatObserver o);

void registerObserver(BPMObserver o);

void removeObserver(BPMObserver o);
}

{code:java}
//==============================================
// 2. BeatModel 구상 클래스
//==============================================
public class BeatModel implements BeatModelInterface{
   Sequencer sequencer;
   ArrayList beatObservers = new ArrayList();
   ArrayList bpmObservers = new ArrayList();
   int bpm = 90;

   public void initialize(){
      setUpMidi();
      buildTrackAndStart();
   }

   public void on(){
      sequencer.start();
      setBPM(90);
   }

   public void off(){
      setBPM(0);
      sequencer.stop();
   }

   public void setBPM(int bpm){
      this.bpm = bpm;
      sequencer.setTempoInBPM(getBPM());
      notifyBPMObservers();
   }

   public int getBPM(){
      return bpm;
   }

   void beatEvent(){
      notifyBeatObservers();
   }

   // 옵저버 등록및 해제용 코드

   // 음악을 만들어내기 위한 미디코드
}

|

컨트롤러 서블릿
{code:java}
//==============================================
// 2. 컨트롤러 서블릿
//==============================================
public class DJView extends HttpServlet{
public void init() throws ServletException{
BeatModel beatModel = new BeatModel();
beatModel.initialize();
getServletContext().setAttribute("beatModel",beatModel);
}

public void doGet(HttpServletRequset request,
HttpServletResponse response)
throws IOException, ServletException
{
BeatModel beatModel =
(BeatModel)getServletContext.getAttribute("beatModel");

String bpm = request.getParameter("bpm");
if(bpm==null){
bpm = beatModel.getBPM() + "";
}

String set = request.getParameter("set");
if(set==null){
int bpmNumber = 90;
bpmNumber = Integer.parseInt(bpm);
beatModel.setBPM(bpmNumber);
}

String decrease = request.getParameter("decrease");
if(decrease==null){
beatModel.setBPM(beatModel.getBPM()-1);
}

String increase = request.getParameter("increase");
if(increase==null){
beatModel.setBPM(beatModel.getBPM()+1);
}

String on = request.getParameter("on");
if(on==null){
beatModel.start();
}

String off = request.getParameter("off");
if(off==null){
beatModel.stop();
}

request.setAttribute("beatModel",beatModel);

RequestDispatcher dispatcher =
request.getRequestDispatcher("/jsp/DJview.jsp");
dispatcher.forward(request.response);
}
}

| {code:java}
//==============================================
// 3. 뷰(JSP)
//==============================================
<jsp:useBean id="beatModel" scope="request" class="headfirst.combined.djview.BeatModel"/>

<html>
<head>
<title>DJ View</title>
</head>
<body>
<h1>DJ View</h1>
Beats per minutes = <jsp:getProperty name="beatModel" property="BPM"/>
<br/>
<hr>
<br/>
<form method="post" action="/djview/servlet/DJView">
BPM: <input type=text name="bpm" value="<jsp:getProperty name="beatModel" property="BPM" />
 
<input type="submit" name="set" value="set"><br/>
<input type="submit" name="decrease" value="<<"><br/>
<input type="submit" name="increase" value=">>"><br/>
<input type="submit" name="on" value="on"><br/>
<input type="submit" name="off" value="off"><br/>
</form>
</html>

|

문서에 대하여