複合模式

定義: 結合兩個或以上的模式在一個解決方案。


又是鴨子範例

首先先建立一個Quackable介面

public interface Quackable {
    public void quack(); //呱呱叫
}

有天某些鴨子實踐了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("Kawk");
    }
}


public class RubberDuck implements Quackable { //橡膠鴨
    public void quack() {
        System.out.println("Squeak");
    }
}

實作囉

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("Duck Simulator");

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

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

}

Duck Simulator
Quack
Quack
Kwak
Squeak

目前為止一切順利


但...此時鵝出現了!

public class Goose {
    public void honk() {
        System.out.println("Honk"); //鵝鵝叫
    }
}

轉接器模式

(弓箭手也想丟火球?
public class GooseAdapter implements Quackable { //轉接器會實踐目的介面
    Goose goose;
    public GooseAdpter(Goose goose) {
        this.goose = goose;
    }

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

把轉接器模式加入(修改code part1)

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("Duck Simulator");

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

    }

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

}

Duck Simulator
Quack
Quack
Kwak
Squeak
Honk

呱呱叫專家要知道叫的次數

裝飾者模式

(星巴茲咖啡 加摩卡加奶泡...
public class QuackCounter implements Quackable { //裝飾者實踐目的介面
    Quackable duck;
    static int numberOfQuacks;

    public QuackCounter (Quackable duck) {
        this.duck = duck;
    }

    public void quack() {
        duck.quack();
        numberOfQuacks++;
    }
    public static int getQuacks() {
        return numberOfQuacks;
    }
}

把裝飾者模式加入(修改code part2)

public class DuckSimulator {
   public static void main(String[] args) {
      DuckSimulator simulator = new DuckSimulator();
      simulator.simulate();
   }

   void simulate() {
      Quackable mallardDuck = new QuackCounter(new MallardDuck()); //用QuackCounter包裝
      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("Duck Simulator");

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

      System.out.println("鴨子叫了" + QuackCounter.getQuacks() + "次");
    }

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

}

Duck Simulator
Quack
Quack
Kwak
Squeak
Honk
鴨子叫了 4

為了品質管制鴨子,確保鴨子一定被包裝進裝飾者中,我們要建立一個工廠產生鴨子

工廠模式

(辭職賣Pizza的故事,建立自己的原料工廠
public abstract class AbstractDuckFactory { //定義抽象工廠

    public abstract Quackable creatMallarDuck(); //每個方法建立一種鴨子
    public abstract Quackable creatRedheadDuck();
    public abstract Quackable creatDuckCall();
    public abstract Quackable creatRubberDuck();

}

鴨子工廠

public DuckFactory extends AbstractDuckFactory { //擴充抽象工廠

    public abstract Quackable creatMallarDuck() { //每一個方法都建立一種鴨子
        return new MallarDuck();
    }
    public abstract Quackable creatRedheadDuck() {
        return new RedheadDuck();
    }
    public abstract Quackable creatDuckCall() {
        return new DuckCall();
    }
    public abstract Quackable creatRubberDuck() {
        return new RubberDuck();
    }

}

加入裝飾者的鴨子工廠

public CountingDuckFactory extends AbstractDuckFactory { //擴充抽象工廠

    public abstract Quackable creatMallarDuck() {
        return new QuackCounter(new MallardDuck());
    }
    public abstract Quackable creatRedheadDuck() {
        return new QuackCounter(new RedheadDuck());
    }
    public abstract Quackable creatDuckCall() {
        return new QuackCounter(new DuckCall());
    }
    public abstract Quackable creatRubberDuck() {
        return new QuackCounter(new RubberDuck());
    }

}

把工廠模式加入(修改code part3)

public class DuckSimulator {
   public static void main(String[] args) {
      DuckSimulator simulator = new DuckSimulator();
      AbstractDuckFactort duckFactory = new CountingDuckFactory(); //建立一個工廠 傳進simulate 

      simulator.simulate(duckFactory);
   }

   void simulate( AbstractDuckFactort duckFactory ) {
      Quackable mallardDuck = duckFactory.creatMallardDuck(); //建立鴨子
      Quackable redheadDuck = duckFactory.createRedheadDuck();
      Quackable duckCall    = duckFactory.createDuckCall();
      Quackable rubberDuck  = duckFactory.createRubberDuck();
      Quackable gooseDuck   = new GooseAdapter(new Goose());


      System.out.println("Duck Simulator : 加入工廠模式");

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

      System.out.println("鴨子叫了" + QuackCounter.getQuacks() + "次");
    }

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

}

Duck Simulator : 加入工廠模式
Quack
Quack
Kwak
Squeak
Honk
鴨子叫了 4//結果與上次一樣,但這次用了數鴨工,確保每隻鴨都有被裝飾到。

結果與上次一樣,但這次用了數鴨工,確保每隻鴨都有被裝飾到。


他們還想管理一群鴨子,

如果我們能夠下一次命令就能讓所有的鴨子聽命令行事

合成模式

(樹狀結構?

將一群物件視為一個物件

public class Flock implements Quackable { //建立一個群
    ArrayList quackers = new ArrayList;

    public void add(Quackable quacker) {
        quackers.add(quacker);
    }
    public void quack() {  
        Iterator iterator = quackers.iterator();  //這裡是反覆器模式
        while (iterator.hasNext()) {
            Quackable quacker = (Quackable)iterator.next();
            quacker.quack();
        }
    }

}

把合成模式加入(修改code part4)

public class DuckSimulator {
   public static void main(String[] args) {
      DuckSimulator simulator = new DuckSimulator();
      AbstractDuckFactort duckFactory = new CountingDuckFactory();

      simulator.simulate(duckFactory);
   }

   void simulate( AbstractDuckFactort duckFactory ) {
      Quackable redheadDuck = duckFactory.createRedheadDuck();
      Quackable duckCall    = duckFactory.createDuckCall();
      Quackable rubberDuck  = duckFactory.createRubberDuck();
      Quackable gooseDuck   = new GooseAdapter(new Goose());

      System.out.println("Duck Simulator : 加入合成模式");

      Flock flockOfDucks = new Flock();  //建立一個主群

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

      Flock flockOfMallards = new Flock(); //再建立一個綠頭鴨群

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

      flockOfMallards.add(mallardOne);   //加入綠頭鴨群
      flockOfMallards.add(mallardTwo);
      flockOfMallards.add(mallardThree);
      flockOfMallards.add(mallardFour);

      flockOfDucks.add(flockOfMallards); //把綠頭鴨加入組群

      System.out.println("鴨主群:");
      simulate(flockOfDucks);

      System.out.println("綠頭鴨群:");
      simulate(flockOfMallards);

      System.out.println("鴨子叫了" + QuackCounter.getQuacks() + "次");
    }

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

}

Duck Simulator : 加入合成模式
鴨主群:
Quack
Kwak
Squeak
Honk
Quack
Quack
Quack
Quack
綠頭鴨群:
Quack
Quack
Quack
Quack

鴨子叫了 11

新需求:能夠追蹤每隻鴨子,當有鴨子叫時,馬上通知。

觀察者模式

(天氣站問題

建立一個 QuackObservable 介面 (呱呱叫的可觀察介面)

public interface QuackObservable { 
    public void registerObserver(Observer observer); //觀察者必須實踐Observer介面
    public void notifyObserver();    //通知觀察者的方法
}

讓Quackable 擴充此介面

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

建立一個輔助類別 Observable (可觀察類)

只要把它插進任何類別,就可讓該類別將工作給Observable進行。

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 notifyObserver() { //通知
        Iterator iterator = observers.iterator();
        while (iterator.hasNext()) {
            Observer observer = (Observer)iterator.next();
            observer.update(duck);
        }
    }
}

修改鴨類別 (綠頭鴨)

public class MallardDuck implements Quackable { 
    Observable observable;

    public void MallardDuck() { //建構式建立Observable
        observable = new Observable(this);
    }
    public void quack() {  
        System.out.println("Quack");
        notifyObserver(); //呱呱叫時要讓觀察者知道

    }
    public void registerObserver(Observer observer) { //把工作交給observable進行
        observable.registerObserver(observer);
    }
    public void notifyObserver() { //把工作交給observable進行
        observable.notifyObservers();
    }


}
...其他鴨也是

建立Observer (觀察者) 介面

public interface Observer {
    public void update(QuackObservable duck);
}

現在我們需要一個觀察者:呱呱叫專家

public class Quackologist implements Observer { //印出正在呱呱叫的物件
   public void update(QuackObservable duck) {
       System.out.println("呱呱叫專家:" + duck + "叫囉");
   }

}

把觀察者模式加入(修改code part5)

public class DuckSimulator {
   public static void main(String[] args) {
      DuckSimulator simulator = new DuckSimulator();
      AbstractDuckFactort duckFactory = new CountingDuckFactory();

      simulator.simulate(duckFactory);
   }

   void simulate( AbstractDuckFactort duckFactory ) {
      Quackable redheadDuck = duckFactory.createRedheadDuck();
      Quackable duckCall    = duckFactory.createDuckCall();
      Quackable rubberDuck  = duckFactory.createRubberDuck();
      Quackable gooseDuck   = new GooseAdapter(new Goose());

      System.out.println("Duck Simulator : 合成模式加入觀察者模式");

      Flock flockOfDucks = new Flock();  //建立一個主群
      flockOfDucks.add(redheadDuck);
      flockOfDucks.add(duckCall);
      flockOfDucks.add(rubberDuck);
      flockOfDucks.add(gooseDuck);

      Quackologist quackologist = new Quackologist(); //建立呱呱叫專家 註冊成為一群觀察者
      flockOfDucks.registerObserver(quackologist); 

      simulate(flockOfDucks); //模擬整群鴨

      System.out.println("鴨子叫了" + QuackCounter.getQuacks() + "次");
    }

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

}

Duck Simulator : 合成模式加入觀察者模式
Quack
呱呱叫專家: Redhead Duck 叫囉  //每一次呱呱叫,觀察者都會收到通知
Kwak
呱呱叫專家: Duck Call叫囉
Squeak
呱呱叫專家: Rubber Duck 叫囉
Honk
呱呱叫專家: 假裝鴨的鵝 叫囉



鴨子叫了 3

我們共做了哪些模式

一開始有一堆鴨子物件

  • 鵝的亂入 => 轉接器模式
  • 需要紀錄呱呱叫的次數 => 裝飾者模式
  • 擔心有漏網之鴨忘了裝飾的鴨子 =>工廠模式
  • 又是鴨 又是鵝 又是 quackable 管理上有困擾 => 合成模式
  • 任何鴨叫時需要被通知 =>觀察者模式

Model = 處理資料

View = 畫面顯示

Controller = M與C溝通橋梁

results matching ""

    No results matching ""