使用模式最棒的方式,就是把他们从家里找出来同其他模式展开交互。这就是复合模式。
我们将重访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的模式.
从设计模式看,模型利用观察者让控制器和视图可以随最新的状态改变而更新。另一方面,视图和控制器则实现了策略模式。控制器是视图的行为,如果你希望不同的行为,可以直接换一个控制器。视图内部使用组合模式来管理窗口、按钮以及其他显示组件。