设计模式(12)Compund Pattern 各种模式的组合使用案例

模式的组合使用

案例一:小鸭子

这里仍然使用书中第一章的鸭子的案例。

首先创建一个“叫”的接口名为Quackable。所有的鸭子都实现这个接口。因为所有的鸭子都能叫。

public interface Quackable{
    public void quack(); 
}

然后我们所有的鸭子,只要能叫,就都要实现这个接口:

/* MallardDuck */
public class MallardDuck implements Quackable {
    public void quack() {
    	System.out.println(“Quack”);
    }
}
/* ReadheadDuck */
public class RedheadDuck implements Quackable {
    public void quack() {
    	System.out.println(“Quack”);
    }
}
public class RubberDuck implements Quackable {
	public void quack() {
		System.out.println("Squeak");
	}
}
public class DuckCall implements Quackable {
	public void quack() {
		System.out.println("Kwak");
	}
}

调用

这是最简单的,使用接口调用。

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();
	}
}

1. Adapter

现在添加一个一个大白鹅的类Goose。

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

显然,Goose类并没有实现Quackable接口,因为Goose的叫声是“鹅鹅鹅饿鹅鹅鹅”而不是“嘎嘎嘎嘎嘎嘎嘎”

那么我们如何在实际调用中使用Quackable接口来实现Goose的调用呢?

对的,写一个Adapter

public class GooseAdapter implements Quackable{
	Goose goose;

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

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

那么我们在调用的时候,就可以通过GooseAdapter使用Quackable来接收Goose咯!

Quackable gooseDuck = new GooseAdapter(new Goose());
gooseDuck.quack();

2. 装饰模式

现在要增加一个功能,我们想记录有多少个quack()被调用,即数一数有多少只鸭子,不算刚才那只大白鹅!

怎么实现呢?显然我们需要一个计数器。这个计数器在每次quack()被调用的时候,就计数一次,还要排除混入的那只大白鹅。试试装饰者模式

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;
	}
}

这样,我们在调用的时候,先将鸭子们装饰一下,增添计数的功能,然后在使用Quackable接口调用

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");
		
		simulate(mallardDuck);
		simulate(redheadDuck);
		simulate(duckCall);
		simulate(rubberDuck);
		simulate(gooseDuck);
    	//getQuacks()是一个静态方法
        System.out.println(“The ducks quacked “ +
    QuackCounter.getQuacks() + “ times”);
		}

**注意:**装饰模式有一个问题,就是想要计数,必须将这个鸭子使用QuackCounter来装饰,一旦哪个忘记了,就无法对这个进行计数了。

3. 工厂模式

工厂设计:

  • 抽象父类
    • 普通鸭子
    • QuackCounter修饰的鸭子
public abstract class AbstractDuckFactory {
	public abstract Quackable createMMallardDuck();
	public abstract Quackable createRedheadDuck();
	public abstract Quackable createDuckCall();
	public abstract Quackable createRubberDuck();
}

/**
 * 生产拥有计数功能的鸭子
 */
public class CountingDuckFactory extends AbstractDuckFactory{

	@Override
	public Quackable createMMallardDuck() {
		return new QuackCounter(new MallardDuck());
	}

	@Override
	public Quackable createRedheadDuck() {
		return new QuackCounter(new RedheadDuck());
	}

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

	@Override
	public Quackable createRubberDuck() {
		return new QuackCounter(new RubberDuck());
	}
}
/**
 * 生产没有计数功能的鸭子
 */
public class DuckFactory extends AbstractDuckFactory{
	
	@Override
	public Quackable createMMallardDuck() {
		return new MallardDuck();
	}

	@Override
	public Quackable createRedheadDuck() {
		return new RedheadDuck();
	}

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

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

我们的测试类可以这样写了:

先new一个工厂,然后使用工厂创建鸭子。鸭子是否能够计数,会根据工厂的不同而确定。

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();
	}
}

4. Composite Pattern组合模式

我们在上面的simulate()函数中,创建鸭子(实际上是创建Quackable)很不好管理。因为他们都是单独的实例。如何更好的管理他们呢?

把他们封装到一个类Flock中。

public class Flock implements Quackable{
	List<Quackable> quackers = new ArrayList<>();
	public void add(Quackable quacker) {
		quackers.add(quacker);
	}
	
	@Override
	public void quack() {
        // 迭代器模式 当然可以for遍历
		Iterator<Quackable> iterator = quackers.iterator();
		while(iterator.hasNext()) {
			Quackable quacker = (Quackable) iterator.next();
			quacker.quack();
		}
	}
}

5. 观察者模式

现在可以同意管理这群鸭子了。但是又出现了新的需求,我们如何能够实时的跟踪某一个鸭子呢???

当然,我们可以尝试观察者模式

观察者模式简单来说,如果某个对象是被观察者,那么他需要维护一个观察他的对象的队列。当他发生变化时,要主动通知观察他的对象们

首先我们定义一个被观察者的接口Observable

public interface QuackObservable {
	public void registerObserver(Observer observer);
	public void notifyObservers();
}

然后,修改我们的Quackable,来继承QuackObservable接口

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

修改完,我们会发现报错了。因为我们值钱所有实现Quackable接口的类都需要添加QuackObservable的方法。

  • 我们可以在每个实现了Quackable接口的类都实现registerObserver()void notifyObservers()方法。
  • 或者我们可以把reisterObservernotifyObservers包装的代码包装到另一个类Observable。然后在每个Quackable的实现类都增加一个Observable的实例
public class MallardDuck implements Quackable{
	Observable observable;
	
	public MallardDuck() {
		this.observable = new Observable();
	}

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

	@Override
	public void registerObserver(Observer observer) {
		observable.registerObserver(observer);
	}

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

所有实现Quackable接口的类都要这样修改。

然后我们设计一个观察者,名字叫Quackologist

public class Quackologist implements Observer{
	@Override
	public void update(QuackObserable duck) {
		System.out.println("Quackologist:" + duck + "just quacked");
	}
}

我们最终的使用方法:

void simulate(AbstractDuckFactory duckFactory) {
    // create duck factories and ducks here
    // create flocks here
    System.out.println(“\nDuck Simulator: With Observer”);
    Quackologist quackologist = new Quackologist();
    flockOfDucks.registerObserver(quackologist);
    simulate(flockOfDucks);
    System.out.println(“\nThe ducks quacked “ +
    QuackCounter.getQuacks() +
    “ times”);
}

注意Flock的修改

public class Flock implements Quackable{
	List<Quackable> quackers = new ArrayList<>();
	public void add(Quackable quacker) {
		quackers.add(quacker);
	}
	
	@Override
	public void quack() {
		Iterator<Quackable> iterator = quackers.iterator();
		while(iterator.hasNext()) {
			Quackable quacker = (Quackable) iterator.next();
			quacker.quack();
		}
	}

	@Override
	public void registerObserver(CompoundPattern.Observer observer) {
		for(Quackable it : quackers) {
			it.registerObserver(observer);
		}
	}

	@Override
	public void notifyObservers() {
		for(Quackable it : quackers) {
			it.notifyObservers();
		}
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值