使用模式最棒的方式,就是把他們從家裏找出來同其他模式展開交互。這就是複合模式。
我們將重訪SimUDuck鴨子模擬器中那些鴨子。
我們將從頭重建我們的鴨子模擬器。
首先,創建一個Quackable接口:
public interface Quackable {
public void quack();
}
某些鴨子實現此接口:
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("Kwak");
}
}
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("\nDuck 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 GooseAdapter(Goose goose){
this.goose=goose;
}
public void quack(){
goose.honk();
}
}
現在在模擬器中可以使用鵝了:
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());//把goose包裝成GooseAdapter
System.out.println("\nDuck 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;
}
}
更新模擬器:
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();
}
}
結果:
Duck Simulator:with decorator
Quack
Quack
Kwak
Squeak
Honk
The ducks quacked 4 times
包裝對象纔有效果,沒包裝就沒效果,我們可以將創建和裝飾的部分包裝起來,工廠模式:
public abstract class AbstractDuckFactory {
public abstract Quackable createMallardDuck();
public abstract Quackable createRedHeadDuck();
public abstract Quackable createDuckCall();
public abstract Quackable createRubberDuck();
}
創建一個沒有裝飾者的工廠:
public class DuckFactory extends AbstractDuckFactory{
@Override
public Quackable createMallardDuck() {
// TODO Auto-generated method stub
return new MallardDuck();
}
@Override
public Quackable createRedHeadDuck() {
// TODO Auto-generated method stub
return new RedHeadDuck();
}
@Override
public Quackable createDuckCall() {
// TODO Auto-generated method stub
return new DuckCall();
}
@Override
public Quackable createRubberDuck() {
// TODO Auto-generated method stub
return new RubberDuck();
}
//模擬器並不知道實際產品是什麼,只知道實現了Quackable接口
}
創建我們想要的工廠:
public class CountingDuckFactory extends AbstractDuckFactory{
@Override
public Quackable createMallardDuck() {
// TODO Auto-generated method stub
return new QuackCounter(new MallardDuck());
}
@Override
public Quackable createRedHeadDuck() {
// TODO Auto-generated method stub
return new QuackCounter(new RedHeadDuck());
}
@Override
public Quackable createDuckCall() {
// TODO Auto-generated method stub
return new QuackCounter(new DuckCall());
}
@Override
public Quackable createRubberDuck() {
// TODO Auto-generated method stub
return new QuackCounter(new RubberDuck());
}
}
設置模擬器:
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.createRedHeadDuck();
Quackable duckCall=duckFactory.createDuckCall();
Quackable rubberDuck=duckFactory.createRubberDuck();
Quackable gooseDuck=new GooseAdapter(new Goose());
System.out.println("\nDuck Simulator:with abstract factory");
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();
}
}
結果:
Duck Simulator:with abstract factory
Quack
Quack
Kwak
Squeak
Honk
The ducks quacked 4 times
現在管理員想管理一羣鴨子,而不是個別,我們可以用到組合模式:
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();
}
}
}
修改模擬器:
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.createRedHeadDuck();
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(rubberDuck);
flockOfDucks.add(duckCall);
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 Simulation");
simulate(flockOfDucks);//測試一整羣
System.out.println("\nDuck Simulator:Mallard Flock Simulation");
simulate(flockOfMallards);//測試綠頭鴨羣
System.out.println("The ducks quacked "+QuackCounter.getQuacks()+" times");
}
void simulate(Quackable duck){
duck.quack();
}
}
結果:
Duck Simulator:with composite-flocks
Duck Simulator:Whole Flock Simulation
Quack
Squeak
Kwak
Honk
Quack
Quack
Quack
Quack
Duck Simulator:Mallard Flock Simulation
Quack
Quack
Quack
Quack
The ducks quacked 11 times
管理員又有新的要求了,需要跟蹤個別的鴨子,我們可以用觀察者模式:
首先需要一個Observable接口;(這裏的Observable就是被觀察者)
public interface QuackObservable {
public void registerObserver(Observer observer);
public void notifyObservers();
}
需要確定所有的quackable都實現此接口:
public interface Quackable extends QuackObservable{
public void quack();
}
確定所有實現Quackable的具體類都扮演QuackObservable的角色:
我們需要在每一個類中實現註冊和通知,這次我們要用稍微不一樣的做法:
我們要在另一個被稱爲Observable的類中封裝註冊和通知的代碼,然後將它和QuackObservable組合在一起。
Observer輔助類:
import java.util.ArrayList;
import java.util.Iterator;
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);
}
}
}
整合Observable輔助類和Quackable類:
下面是MallardDuck實現,其他一樣
public class MallardDuck implements Quackable{
Observable observable;
public MallardDuck(){
observable=new Observable(this);
}
public void quack(){
System.out.println("Quack");
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
// TODO Auto-generated method stub
observable.registerObserver(observer);
}
@Override
public void notifyObservers() {
// TODO Auto-generated method stub
observable.notifyObservers();
}
}
QuackCOunter裝飾者
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;
}
@Override
public void registerObserver(Observer observer) {
// TODO Auto-generated method stub
duck.registerObserver(observer);
}
@Override
public void notifyObservers() {
// TODO Auto-generated method stub
duck.notifyObservers();
}
}
Observer端:
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.");
}
}
如果要觀察整個羣的話:
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();
}
}
@Override
public void registerObserver(Observer observer) {
// TODO Auto-generated method stub
Iterator iterator=quackers.iterator();
while(iterator.hasNext()){
Quackable duck=(Quackable)iterator.next();
duck.registerObserver(observer);
}
}
@Override
public void notifyObservers() {
// TODO Auto-generated method stub
}
}
更新模擬器:
public class DuckSimulator {
public static void main(String[]args){
DuckSimulator simulator=new DuckSimulator();
AbstractDuckFactory duckFactory=new CountingDuckFactory();
simulator.simulate(duckFactory);
}
void simulate(AbstractDuckFactory duckFactory){
System.out.println("\nDuck Simulator:with observer");
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);
Quackologist quackologist=new Quackologist();
flockOfMallards.registerObserver(quackologist);
simulate(flockOfMallards);
System.out.println("The ducks quacked "+QuackCounter.getQuacks()+" times");
}
void simulate(Quackable duck){
duck.quack();
}
}
結果:
Duck Simulator:with observer
Quack
Quackologist: duck.MallardDuck@4aa0b07b just quacked.
Quack
Quackologist: duck.MallardDuck@7ba28183 just quacked.
Quack
Quackologist: duck.MallardDuck@69e4fede just quacked.
Quack
Quackologist: duck.MallardDuck@3918d722 just quacked.
The ducks quacked 4 times
這個例子主要的目的是展示許多模式可以合作,真實的設計過程中,不會想要這麼做,不然有點殺雞用牛刀的趕腳。
MVC模式是一個典型的複合模式。
MVC,即model-view-controller,比如一個MP3播放器底層就是MVC模式。
1、你是用戶,你和視圖交互。視圖是模型的窗口。
2、控制器要求模型狀態改變。
3、控制器也有可能要求視圖做改變。
4、模型狀態改變時,模型會通知視圖。
5、視圖向模型詢問狀態。
最典型的MVC就是JSP + servlet + javabean的模式.
從設計模式看,模型利用觀察者讓控制器和視圖可以隨最新的狀態改變而更新。另一方面,視圖和控制器則實現了策略模式。控制器是視圖的行爲,如果你希望不同的行爲,可以直接換一個控制器。視圖內部使用組合模式來管理窗口、按鈕以及其他顯示組件。