策略模式
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
公司做了一个模拟鸭子的游戏,这些鸭子可以叫和游泳,现在想让这些鸭子飞
这样做会让橡皮鸭也具备飞的行为,虽然在fly()中可以不做任何动作,如果每次进来一个鸭子就覆盖方法,很不好,例如:诱饵鸭不会飞也不会叫,橡皮鸭不会飞也不会叫
将飞和叫的行为弄成接口会造成代码无法复用
把飞行和交的行为弄成接口,具体的叫法由类具体实现
public interface FlyBehavior {
/*
* 飞行行为接口
*/
public void fly();
}
public class FlyNoWay implements FlyBehavior {
/*
* 不能飞行的行为
*/
@Override
public void fly() {
System.out.println("I can't fly");
}
}
public class FlyWithWings implements FlyBehavior {
/*
* 可以飞行的行为
*/
@Override
public void fly() {
System.out.println("I'm flying");
}
}
public interface QuackBehavior {
/*
* 叫的行为接口
*/
public void quack();
}
public class Quack implements QuackBehavior {
/*
* 嘎嘎叫
*/
@Override
public void quack() {
System.out.println("quack");
}
}
public class Squeak implements QuackBehavior{
/*
* 吱吱叫
*/
@Override
public void quack() {
System.out.println("squeak");
}
}
public abstract class Duck {
/*
* 鸭子抽象类
*/
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {};
public abstract void displaly();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float");
}
//可以动态设置鸭子的行为
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
public class MallardDuck extends Duck{
/*
* 绿头鸭实现类
*/
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
@Override
public void displaly() {
System.out.println("I'm a real Mallard duck");
}
}
public class MiniDuckSimulator {
/*
* 测试类
*/
public static void main(String[] args) {
Duck mallard = new MallardDuck();
//I'm flying
mallard.performFly();
//quack
mallard.performQuack();
}
}
加上一个模型鸭,使模型鸭可以动态改变行为,在后期使模型鸭具有火箭动力
public class FlyRocketPowered implements FlyBehavior {
/*
* 具有火箭动力的飞行
*/
@Override
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
public class ModelDuck extends Duck {
/*
* 模型鸭
*/
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
@Override
public void displaly() {
System.out.println("I'm a model duck");
}
}
public class MiniDuckSimulator {
/*
* 测试类
*/
public static void main(String[] args) {
Duck mallard = new MallardDuck();
//I'm flying
mallard.performFly();
//quack
mallard.performQuack();
Duck model = new ModelDuck();
//I can't fly
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
//I'm flying with a rocket
model.performFly();
}
}
观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新
为了展示气象数据而封装了一个数据对象WeatherData,当气象数据更新的时候,所有布告板上的显示都得发生改变,这时系统调用WeaherData对象的measurementsChanged()方法,错误的示例如下:
定义观察者模式
最终的类图
public interface Subject {
/*
* 主题对象实现的接口
*/
//注册观察者
public void registerObserver(Observer o);
//删除观察者
public void removeObserver(Observer o);
//当主题状态改变时,这个方法会被调用,以通知所有的的观察者
public void notifyObservers();
}
public interface Observer {
/*
* 观察者对象实现的接口
*/
public void update(float temp, float humidity, float pressure);
}
public interface DisplayElement {
/*
* 展示行为的接口
*/
public void display();
}
实现气象数据对象
public class WeatherData implements Subject{
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
@Override
public void notifyObservers() {
for (int i=0; i<observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
实现布告板
public class CurrentConditionsDisplay implements Observer, DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
测试类
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
//Current conditions: 80.0F degrees and 65.0% humidity
weatherData.setMeasurements(80, 65, 30.4f);
}
}
装饰者模式
装饰者模式动态的将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择,可以在不修改底层代码的情况下,给对象赋予新的职责
咖啡店的类设计原来是这样的
但是顾客会要求加入各种调料,如蒸奶(Steamed Milk),豆浆(Soy)
用父类计算调料的价钱,子类计算饮料的价钱
哪些需求或因素改变时会影响这个设计
以装饰者构造饮料订单
装饰者模式动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
public abstract class Beverage {
/*
* Beverage类
*/
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
public abstract class CondimentDecorator extends Beverage{
/*
* 调料装饰抽象类
*/
@Override
public abstract String getDescription();
}
public class Espresso extends Beverage {
/*
* 浓缩咖啡类
*/
public Espresso() {
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage {
/*
* 另一种咖啡类
*/
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return 0.89;
}
}
已经有了抽象组件(Beverage),具体组件(HouseBlend),抽象装饰者(CondimentDecorator),下面实现具体装饰者
public class Mocha extends CondimentDecorator {
/*
* 摩卡装饰者
*/
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost() {
return 0.20 + beverage.cost();
}
}
public class Whip extends CondimentDecorator {
/*
* 奶油装饰者
*/
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
@Override
public double cost() {
return 0.58 + beverage.cost();
}
}
public class StarBuzzCoffee {
public static void main(String[] args) {
/*
* 测试类
*/
Beverage beverage = new Espresso();
//Espresso $1.99
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage2 = new HouseBlend();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
//House Blend Coffee, Mocha, Mocha, Whip $1.87
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}
装饰Java io类
test.txt
This Is Just For Test
public class LowerCaseInputStream extends FilterInputStream {
/*
* 自己的装饰类,将大写字母转为小写字母
*/
protected LowerCaseInputStream(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1 ? -1 : Character.toLowerCase((char)c));
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int result = super.read(b, off, len);
for (int i=off; i<=off+result; i++) {
b[i] = (byte)Character.toLowerCase((char)b[i]);
}
return result;
}
}
public class InputTest {
public static void main(String[] args) {
/*
* 测试自己的装饰类
*/
int c;
try {
InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
while ((c = in.read()) >= 0) {
//this is just for test
System.out.print((char)c);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
工厂模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类
有订购披萨的工具如下
当披萨菜单发生改变时,代码必须进行修改。我们可以把创建对象移到orderPizza()之外,如下所示
public abstract class Pizza {
/*
* 披萨类
*/
String name;
//面团
String dough;
//酱
String sauce;
//糕点上的装饰配料
ArrayList toppings = new ArrayList();
void prepare() {
System.out.println("Preparing " + name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
System.out.println("Adding toppings : ");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
//烤
void bake() {
System.out.println("Bake for 25 minutes at 350");
}
void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}
void box() {
System.out.println("Place pizza in official PizzaStore box");
}
String getName() {
return name;
}
}
public class NYStyleCheesePizza extends Pizza{
/*
* 纽约风味的芝士披萨类
*/
public NYStyleCheesePizza() {
//大蒜番茄酱和薄饼
name = "NY Style Sauce and Chees Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.add("Grated Reggiano Cheese");
}
}
public class ChicagoStyleCheesePizza extends Pizza {
/*
* 芝加哥风味的芝士披萨
*/
public ChicagoStyleCheesePizza() {
//小番茄厚饼
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.add("Shredded Mozzarella Cheese");
}
void cut() {
//覆盖了cut()方法,将披萨切成正方形
System.out.println("Cutting the pizza into square slices");
}
}
public abstract class PizzaStore {
/*
* 披萨店的抽象类
*/
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
//工厂方法是抽象的
protected abstract Pizza createPizza(String type);
}
public class NYPizzaStore extends PizzaStore{
/*
* 纽约风味的披萨店
*/
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (type.equals("veggie")) {
//没有写这个类,只是举一个例子,动态的创建类
//return new NYStyleVeggiePizza();
}
return null;
}
}
public class ChicagoPizzaStore extends PizzaStore{
/*
* 芝加哥风味的披萨店
*/
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new ChicagoStyleCheesePizza();
} else if (type.equals("veggie")) {
//根据要求动态创建类
//return new ChicagoStyleVeggiePizza();
}
return null;
}
}
测试类
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
/*Preparing NY Style Sauce and Chees Pizza
Tossing dough...
Adding sauce...
Adding toppings :
Grated Reggiano Cheese
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box*/
Pizza pizza = nyStore.orderPizza("cheese");
//order a NY Style Sauce and Chees Pizza
System.out.println("order a " + pizza.getName() + "\n");
/*Preparing Chicago Style Deep Dish Cheese Pizza
Tossing dough...
Adding sauce...
Adding toppings :
Shredded Mozzarella Cheese
Bake for 25 minutes at 350
Cutting the pizza into square slices
Place pizza in official PizzaStore box*/
pizza = chicagoStore.orderPizza("cheese");
//order a Chicago Style Deep Dish Cheese Pizza
System.out.println("order a " + pizza.getName() + "\n");
}
}
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
现在,我们要建造一个工厂来生产原料,这个工厂负责创建原料家族中的每一种原料,因为每个地区所需要的原料是不同的
public interface PizzaIngredientFactory {
/*
* 披萨原料工厂的抽象类
*/
//面团
public Dough createDough();
//酱
public Sauce createSauce();
//奶酪
public Cheese createCheese();
//蔬菜
public Veggies[] createVeggies();
//意大利辣味香肠
public Pepperoni createPepperoni();
//蛤
public Clams createClam();
}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory{
/*
* 纽约披萨原料工厂类
*/
@Override
public Dough createDough() {
return new ThinCrustDough();
}
@Override
public Sauce createSauce() {
return new MarinaraSauce();
}
@Override
public Cheese createCheese() {
return new ReggianoCheese();
}
@Override
public Veggies[] createVeggies() {
//里面的原料实现Veggies的接口类
Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
return veggies;
}
@Override
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
@Override
public Clams createClam() {
return new FreshClams();
}
}
public abstract class Pizza {
/*
* 修改后的披萨类
*/
String name;
//可以将dough弄为一个接口,让具体的类实现它
Dough dough;
//同理将sauce弄为一个接口
Sauce sauce;
//将veggies弄为一个接口
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
//把prepare方法声明成抽象。在这个方法中,我们需要收集披萨所需的原料,而这些原料当然是来自原料工厂了
abstract void prepare();
void bake() {
System.out.println("Bake for 25 minutes at 350");
}
void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}
void box() {
System.out.println("Place pizza in official PizzaStore box");
}
void setName(String name) {
this.name = name;
}
String getName() {
return name;
}
}
public class CheesePizza extends Pizza{
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
@Override
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
public class NYPizzaStore extends PizzaStore {
/*
* 修改后的纽约风味的披萨店
*/
@Override
protected Pizza createPizza(String type) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory =
new NYPizzaIngredientFactory();
if (type.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese Pizza");
} else if (type.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza");
} else if (type.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
}
return pizza;
}
}
看类图了解关系
从PizzaStore的观点来看
单例模式
单例模式确保一个类只有一个实例,并提供全局访问点
经典的单例模式实现
public class Singleton {
//独特的实例
private static Singleton uniqueInstance;
//私有化构造函数,这样就不能通过new来创建这个对象
private Singleton() {}
//声明为静态方法,这样就可通过Singleton.getInstance()方法来获得Singleton对象
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
如果是多线程则会造成问题,解决方法一
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
这样会对性能造成问题,解决方法二
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
加载类时直接创建,解决方法三
public class Singleton {
//volatile关键字确保,当uniqueInstance变量被初始化成Singleton实例时,
//多个线程正确地处理uniqueInstance变量
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
命令模式
命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作
有一个遥控器,有7个插槽,每个插槽有开和关2个按钮用来操作电器,类似如下实现是非常糟糕的,有新厂商进来就得修改代码
if (slot1 == Light) {
light.on()
} else if (slot1 = TV) {
tv.on()
}
一种借鉴的思路是去餐厅吃饭,服务员把你想吃的东西写到菜单上,然后把菜单给了厨师,厨师按照菜单做就行,而不是让服务员直接告诉厨师应该做哪些东西,先写一个简单的Demo
public interface Command {
/*
* 命令接口
*/
public void execute();
}
public class Light {
/*
* 灯类
*/
public Light() {
}
public void on() {
System.out.println("Light is on");
}
public void off() {
System.out.println("Light is off");
}
}
public class LightOnCommand implements Command{
/*
* 打开灯的命令
*/
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
public class SimpleRemoteControl {
/*
* 简单遥控器类
*/
Command slot;
public SimpleRemoteControl() {}
public void setCommand(Command command) {
slot = command;
}
public void buttonWasPressed() {
slot.execute();
}
}
测试类
public class RemoteControlTest {
public static void main(String[] args) {
SimpleRemoteControl remote = new SimpleRemoteControl();
Light light = new Light();
LightOnCommand lightOn = new LightOnCommand(light);
remote.setCommand(lightOn);
//Light is on
remote.buttonWasPressed();
}
}
命令模式的作用:
- 队列请求–>日程安排,线程池,工作队列,想象有一个工作队列:你在某一端添加命令,然后另一端是线程。线程进行下面的动作:从嘟列中取出一个命令,调用它的execute()方法,等待这个调用完成,然后将此命令丢弃,再取出下一个命令,这样工作队列类和进行计算的对象之间是完全解耦的,此刻线程可能进行财务运算,下一刻却在读取网路数据。工作队列只知道取出命令对象,然后调用其execute()方法。
- 日志请求–>某些应用需要我们将所有的动作都记录在日志中,并能在系统死机之后,重新调用这些动作恢复到之前的状态
适配器模式
适配器模式将一个类的接口,装换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间
包装了鸭子适配器的火鸡
public interface Duck {
/*
* 鸭子接口
*/
public void quack();
public void fly();
}
public interface Turkey {
/*
* 火鸡接口
*/
public void gobble();
public void fly();
}
public class MallardDuck implements Duck {
/*
* 野鸭类
*/
@Override
public void quack() {
System.out.println("Quack");
}
@Override
public void fly() {
System.out.println("I'm flying");
}
}
public class WildTurkey implements Turkey {
/*
* 野生火鸡类
*/
@Override
public void gobble() {
System.out.println("Gobble gobble");
}
@Override
public void fly() {
System.out.println("I'm flying a short distance");
}
}
public class TurkeyAdapter implements Duck {
/*
* 适配器类
*/
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
@Override
public void quack() {
turkey.gobble();
}
@Override
public void fly() {
//多飞几次模拟鸭子
for (int i=0; i<3; i++)
turkey.fly();
}
}
public class DuckTest {
/*
* 测试类
*/
public static void main(String[] args) {
Duck duck = new MallardDuck();
//Quack
duck.quack();
//I'm flying
duck.fly();
WildTurkey turkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(turkey);
//Gobble gobble
turkeyAdapter.quack();
//I'm flying a short distance
//I'm flying a short distance
//I'm flying a short distance
turkeyAdapter.fly();
}
}
类图
外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用
当我们在家庭影院观看电影时,要做很多事情,如打开爆米花机,开始爆米花,将灯光调暗,放下屏幕等,我们可以通过实现一个提供更合理的接口的外观类,将一个复杂的子系统变得容易使用
public class HomeTheaterFacade {
/*
* 家庭影院外观类
*/
Amplifier amp;
Tuner tuner;
DvdPlayer dvd;
CdPlayer cd;
Projector projector;
TheaterLights lights;
Screen screen;
PopcornPopper popper;
public HomeTheaterFacade(Amplifier amp,
Tuner tuner,
DvdPlayer dvd,
CdPlayer cd,
Projector projector,
Screen screen,
TheaterLights lights,
PopcornPopper popper) {
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.projector = projector;
this.screen = screen;
this.lights = lights;
this.popper = popper;
}
public void watchMovie(String movie) {
System.out.println("Get ready to watch a movie...");
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}
public void endMovie() {
System.out.println("Shutting movie theater down...");
popper.off();
lights.on();
screen.up();
projector.off();
amp.off();
dvd.stop();
dvd.eject();
dvd.off();
}
}
当我们想看电影时,只要调用watchMovie()方法,关闭电影时只要调用endMovie()方法,省去了很多繁琐的操作
类图
模板方法模式
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤
要开发咖啡和茶的冲泡方法,它们的过程如下:
刚开始我们想到的是抽取咖啡和茶
其中prepareRecipe()方法是包含四个方法的合集,接着我们对2步和第4步不同的部分进一步抽象,抽象出一个咖啡因饮料的类
public abstract class CaffeineBeverage {
/*
* 咖啡因饮料是一个抽象类
*/
//不希望子类覆盖这个方法,并且将步骤2和步骤4泛化为brew()和addCondiments()
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
protected abstract void brew();
protected abstract void addCondiments();
private void boilWater() {
System.out.println("Boiling water");
}
private void pourInCup() {
System.out.println("Pouring into cup");
}
}
public class Tea extends CaffeineBeverage{
@Override
protected void brew() {
System.out.println("Steeping the tea");
}
@Override
protected void addCondiments() {
System.out.println("Adding Lemon");
}
}
public class Coffee extends CaffeineBeverage{
@Override
protected void brew() {
System.out.println("Dripping Coffee through filter");
}
@Override
protected void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
}
测试类
public class BeverageTestDrive {
public static void main(String[] args) {
Tea tea = new Tea();
/*Boiling water
Steeping the tea
Pouring into cup
Adding Lemon*/
tea.prepareRecipe();
}
}
看看抽象类可以有哪些类型的方法
接下来我们队模板方法进行挂钩(只写出了变化的部分)
public abstract class CaffeineBeverage {
/*
* 咖啡因饮料是一个抽象类
*/
//不希望子类覆盖这个方法,并且将步骤2和步骤4泛化为brew()和addCondiments()
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
//如果顾客想要调料,只有这时我们才调用addCondiments()
if (customerWantsClondiments()) {
addCondiments();
}
}
//定义了一个空的缺省实现,子类可以覆盖,但不见得一定要这么做
boolean customerWantsClondiments() {
return true;
}
}
public class Coffee extends CaffeineBeverage{
@Override
boolean customerWantsClondiments() {
String answer = getUserInput();
if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}
private String getUserInput() {
String answer = null;
System.out.println("Would you like milk and sugar with you coffee (y/n) ?");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
} catch (IOException e) {
System.err.println("IO error trying to read your answer");
}
if (answer == null) {
return "no";
}
return answer;
}
}
测试类
public class BeverageTestDrive {
public static void main(String[] args) {
Coffee coffee = new Coffee();
/*Boiling water
Dripping Coffee through filter
Pouring into cup
Would you like milk and sugar with you coffee (y/n) ? y
Adding Sugarand Milk*/
coffee.prepareRecipe();
}
}
用模板方法排序
迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示
对象村餐厅和对象村煎饼屋进行合并,他们都同意菜单的表示方法,即MenuItem类,但煎饼屋是用ArrayList进行存储,餐厅是用数组存储,如果每次是获取容器在进行遍历,非常不方便,菜单的定义如下。
public class MenuItem {
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name,
String description,
boolean vegetarian,
double price)
{
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public double getPrice() {
return price;
}
public boolean isVegetarian() {
return vegetarian;
}
public String toString() {
return (name + ", $" + price + "\n " + description);
}
}
可以让菜单都继承Menu这个接口,接口的作用是使每个菜单都能通过统一的方法获得各自的Iterator
public interface Menu {
public Iterator createIterator();
}
Iterator这个接口规定了遍历的方法
public interface Iterator {
boolean hasNext();
Object next();
}
餐厅存储实现类
public class DinerMenu implements Menu {
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
public DinerMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("Vegetarian BLT",
"(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);
addItem("BLT",
"Bacon with lettuce & tomato on whole wheat", false, 2.99);
addItem("Soup of the day",
"Soup of the day, with a side of potato salad", false, 3.29);
addItem("Hotdog",
"A hot dog, with saurkraut, relish, onions, topped with cheese",
false, 3.05);
addItem("Steamed Veggies and Brown Rice",
"Steamed vegetables over brown rice", true, 3.99);
addItem("Pasta",
"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
true, 3.89);
}
public void addItem(String name, String description,
boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.err.println("Sorry, menu is full! Can't add item to menu");
} else {
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems + 1;
}
}
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}
// other menu methods here
}
餐厅存储遍历类
public class DinerMenuIterator implements Iterator {
MenuItem[] items;
int position = 0;
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
public Object next() {
MenuItem menuItem = items[position];
position = position + 1;
return menuItem;
}
public boolean hasNext() {
if (position >= items.length || items[position] == null) {
return false;
} else {
return true;
}
}
}
煎饼存储实现类
public class PancakeHouseMenu implements Menu {
ArrayList menuItems;
public PancakeHouseMenu() {
menuItems = new ArrayList();
addItem("K&B's Pancake Breakfast",
"Pancakes with scrambled eggs, and toast",
true,
2.99);
addItem("Regular Pancake Breakfast",
"Pancakes with fried eggs, sausage",
false,
2.99);
addItem("Blueberry Pancakes",
"Pancakes made with fresh blueberries",
true,
3.49);
addItem("Waffles",
"Waffles, with your choice of blueberries or strawberries",
true,
3.59);
}
public void addItem(String name, String description,
boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public Iterator createIterator() {
return new PancakeHouseMenuIterator(menuItems);
}
public String toString() {
return "Objectville Pancake House Menu";
}
// other menu methods here
}
当然,上述的createIterator方法可以用ArrayList的iterator()方法
煎饼遍历类
public class PancakeHouseMenuIterator implements Iterator {
ArrayList items;
int position = 0;
public PancakeHouseMenuIterator(ArrayList items) {
this.items = items;
}
public Object next() {
Object object = items.get(position);
position = position + 1;
return object;
}
public boolean hasNext() {
if (position >= items.size()) {
return false;
} else {
return true;
}
}
}
服务员类
public class Waitress {
Menu pancakeHouseMenu;
Menu dinerMenu;
public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
Iterator pancakeIterator = pancakeHouseMenu.createIterator();
Iterator dinerIterator = dinerMenu.createIterator();
System.out.println("MENU\n----\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}
private void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next();
System.out.print(menuItem.getName() + ", ");
System.out.print(menuItem.getPrice() + " -- ");
System.out.println(menuItem.getDescription());
}
}
public void printVegetarianMenu() {
printVegetarianMenu(pancakeHouseMenu.createIterator());
printVegetarianMenu(dinerMenu.createIterator());
}
public boolean isItemVegetarian(String name) {
Iterator breakfastIterator = pancakeHouseMenu.createIterator();
if (isVegetarian(name, breakfastIterator)) {
return true;
}
Iterator dinnerIterator = dinerMenu.createIterator();
if (isVegetarian(name, dinnerIterator)) {
return true;
}
return false;
}
private void printVegetarianMenu(Iterator iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next();
if (menuItem.isVegetarian()) {
System.out.print(menuItem.getName());
System.out.println("\t\t" + menuItem.getPrice());
System.out.println("\t" + menuItem.getDescription());
}
}
}
private boolean isVegetarian(String name, Iterator iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next();
if (menuItem.getName().equals(name)) {
if (menuItem.isVegetarian()) {
return true;
}
}
}
return false;
}
}
测试类
public class MenuTestDrive {
public static void main(String args[]) {
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
DinerMenu dinerMenu = new DinerMenu();
Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
/*
MENU
----
BREAKFAST
K&B's Pancake Breakfast, 2.99 -- Pancakes with scrambled eggs, and toast
Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
Blueberry Pancakes, 3.49 -- Pancakes made with fresh blueberries
Waffles, 3.59 -- Waffles, with your choice of blueberries or strawberries
LUNCH
Vegetarian BLT, 2.99 -- (Fakin') Bacon with lettuce & tomato on whole wheat
BLT, 2.99 -- Bacon with lettuce & tomato on whole wheat
Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
Steamed Veggies and Brown Rice, 3.99 -- Steamed vegetables over brown rice
Pasta, 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread
*/
waitress.printMenu();
}
}
类图如下
组合模式
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合
新的问题来了,每次加入新的菜单时,服务员的printMenu(Iterator)方法就得被调用,如上2个菜单调用了2次,3个菜单就得调用三次,这是一个不好的实现
然而我们不仅想支持多个菜单,还想支持菜单中的菜单,如下所示,将甜点菜单变成餐厅菜单集合的一个元素
组合模式的类图如下
改写餐厅菜单的类图
public abstract class MenuComponent {
/*
* 菜单组件抽象类
*/
public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public MenuComponent getChild(int i) {
throw new UnsupportedOperationException();
}
public String getName() {
throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException();
}
public double getPrice() {
throw new UnsupportedOperationException();
}
public boolean isVegetarian() {
throw new UnsupportedOperationException();
}
public abstract Iterator createIterator();
public void print() {
throw new UnsupportedOperationException();
}
}
import java.util.ArrayList;
import java.util.Iterator;
public class Menu extends MenuComponent{
/*
* 菜单类,即组合类
*/
ArrayList menuComponents = new ArrayList();
String name;
String description;
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
public void add(MenuComponent menuComponent) {
menuComponents.add(menuComponent);
}
public void remove(MenuComponent menuComponent) {
menuComponents.remove(menuComponent);
}
public MenuComponent getChild(int i) {
return (MenuComponent)menuComponents.get(i);
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
@Override
public Iterator createIterator() {
return new CompositeIterator(menuComponents.iterator());
}
public void print() {
System.out.print("\n" + getName());
System.out.println(", " + getDescription());
System.out.println("---------------------");
Iterator iterator = menuComponents.iterator();
while (iterator.hasNext()) {
MenuComponent menuComponent = (MenuComponent)iterator.next();
menuComponent.print();
}
}
}
import java.util.Iterator;
public class MenuItem extends MenuComponent{
/*
* 菜单项类,这是组合类图里的叶类
*/
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name,
String description,
boolean vegetarian,
double price)
{
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public double getPrice() {
return price;
}
public boolean isVegetarian() {
return vegetarian;
}
@Override
public Iterator createIterator() {
return new NullIterator();
}
public void print() {
System.out.println(" " + getName());
if (isVegetarian()) {
System.out.println("(v)");
}
System.out.println(", " + getPrice());
System.out.println(" ----" + getDescription());
}
}
import java.util.Iterator;
import java.util.Stack;
public class CompositeIterator implements Iterator{
/*
* 组合迭代器,遍历菜单和子菜单
*/
Stack stack = new Stack();
public CompositeIterator(Iterator iterator) {
stack.push(iterator);
}
@Override
public boolean hasNext() {
if (stack.empty()) {
return false;
} else {
//peek方法不弹出栈顶
Iterator iterator = (Iterator) stack.peek();
if (!iterator.hasNext()) {
//子组合已经没有菜单项了,将栈顶元素弹出
stack.pop();
//返回下一个子组合的结果
return hasNext();
} else {
return true;
}
}
}
@Override
public Object next() {
if (hasNext()) {
//peek方法不弹出栈顶元素
Iterator iterator = (Iterator) stack.peek();
MenuComponent component = (MenuComponent) iterator.next();
if (component instanceof Menu) {
stack.push(component.createIterator());
}
return component;
} else {
return null;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
import java.util.Iterator;
public class NullIterator implements Iterator{
@Override
public boolean hasNext() {
return false;
}
@Override
public Object next() {
return null;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
我们可以让菜单项的createIterator()方法返回null,但是如果这么做,我们的客户代码就需要条件语句来判断返回值是否为null,因此我们创建一个迭代器,其作用是“没作用”
import java.util.Iterator;
public class Waitress {
/*
* 服务员类
*/
MenuComponent allMenus;
public Waitress(MenuComponent allMenus) {
this.allMenus = allMenus;
}
public void printMenu() {
allMenus.print();
}
public void printVegetarianMenu() {
Iterator iterator = allMenus.createIterator();
System.out.println("\nVEGETARIAN MENU\n----");
while (iterator.hasNext()) {
MenuComponent menuComponent = (MenuComponent)iterator.next();
try {
if (menuComponent.isVegetarian()) {
menuComponent.print();
}
} catch (UnsupportedOperationException e) {}
}
}
}
测试类
public class MenuTestDrive {
public static void main(String args[]) {
MenuComponent dinerMenu = new Menu("DINER MENU", "Lunch");
MenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner");
MenuComponent dessertMenu = new Menu("DESSERT MENU", "Dessert of course!");
MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");
allMenus.add(dinerMenu);
allMenus.add(cafeMenu);
dinerMenu.add(new MenuItem(
"Vegetarian BLT",
"(Fakin') Bacon with lettuce & tomato on whole wheat",
true,
2.99));
dinerMenu.add(new MenuItem(
"BLT",
"Bacon with lettuce & tomato on whole wheat",
false,
2.99));
//将dessertMenu作为dinerMenu的子菜单
dinerMenu.add(dessertMenu);
dessertMenu.add(new MenuItem(
"Apple Pie",
"Apple pie with a flakey crust, topped with vanilla icecream",
true,
1.59));
dessertMenu.add(new MenuItem(
"Cheesecake",
"Creamy New York cheesecake, with a chocolate graham crust",
true,
1.99));
cafeMenu.add(new MenuItem(
"Veggie Burger and Air Fries",
"Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
true,
3.99));
cafeMenu.add(new MenuItem(
"Soup of the day",
"A cup of the soup of the day, with a side salad",
false,
3.69));
Waitress waitress = new Waitress(allMenus);
waitress.printMenu();
waitress.printVegetarianMenu();
}
}
输出
ALL MENUS, All menus combined
---------------------
DINER MENU, Lunch
---------------------
Vegetarian BLT
(v)
, 2.99
----(Fakin') Bacon with lettuce & tomato on whole wheat
BLT
, 2.99
----Bacon with lettuce & tomato on whole wheat
DESSERT MENU, Dessert of course!
---------------------
Apple Pie
(v)
, 1.59
----Apple pie with a flakey crust, topped with vanilla icecream
Cheesecake
(v)
, 1.99
----Creamy New York cheesecake, with a chocolate graham crust
CAFE MENU, Dinner
---------------------
Veggie Burger and Air Fries
(v)
, 3.99
----Veggie burger on a whole wheat bun, lettuce, tomato, and fries
Soup of the day
, 3.69
----A cup of the soup of the day, with a side salad
VEGETARIAN MENU
----
Vegetarian BLT
(v)
, 2.99
----(Fakin') Bacon with lettuce & tomato on whole wheat
Apple Pie
(v)
, 1.59
----Apple pie with a flakey crust, topped with vanilla icecream
Cheesecake
(v)
, 1.99
----Creamy New York cheesecake, with a chocolate graham crust
Apple Pie
(v)
, 1.59
----Apple pie with a flakey crust, topped with vanilla icecream
Cheesecake
(v)
, 1.99
----Creamy New York cheesecake, with a chocolate graham crust
Veggie Burger and Air Fries
(v)
, 3.99
----Veggie burger on a whole wheat bun, lettuce, tomato, and fries
状态模式
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类
我们想让糖果机按照如下方式工作
系统从没有25分钱开始,刚开始实现如下:
public class GumballMachine {
//糖果售完状态
final static int SOLD_OUT = 0;
final static int NO_QUARTER = 1;
final static int HAS_QUARTER = 2;
final static int SOLD = 3;
int state = SOLD_OUT;
int count = 0;
public GumballMachine(int count) {
this.count = count;
if (count > 0) {
state = NO_QUARTER;
}
}
public void insertQuarter() {
if (state == HAS_QUARTER) {
System.out.println("You can't insert another quarter");
} else if (state == NO_QUARTER) {
state = HAS_QUARTER;
System.out.println("You inserted a quarter");
} else if (state == SOLD_OUT) {
System.out.println("You can't insert a quarter, the machine is sold out");
} else if (state == SOLD) {
System.out.println("Please wait, we're already giving you a gumball");
}
}
public void ejectQuarter() {
if (state == HAS_QUARTER) {
System.out.println("Quarter returned");
state = NO_QUARTER;
} else if (state == NO_QUARTER) {
System.out.println("You haven't inserted a quarter");
} else if (state == SOLD) {
System.out.println("Sorry, you already turned the crank");
} else if (state == SOLD_OUT) {
System.out.println("You can't eject, you haven't inserted a quarter yet");
}
}
public void turnCrank() {
if (state == SOLD) {
System.out.println("Turning twice doesn't get you another gumball!");
} else if (state == NO_QUARTER) {
System.out.println("You turned but there's no quarter");
} else if (state == SOLD_OUT) {
System.out.println("You turned, but there are no gumballs");
} else if (state == HAS_QUARTER) {
System.out.println("You turned...");
state = SOLD;
dispense();
}
}
public void dispense() {
if (state == SOLD) {
System.out.println("A gumball comes rolling out the slot");
count = count - 1;
if (count == 0) {
System.out.println("Oops, out of gumballs!");
state = SOLD_OUT;
} else {
state = NO_QUARTER;
}
} else if (state == NO_QUARTER) {
System.out.println("You need to pay first");
} else if (state == SOLD_OUT) {
System.out.println("No gumball dispensed");
} else if (state == HAS_QUARTER) {
System.out.println("No gumball dispensed");
}
}
public void refill(int numGumBalls) {
this.count = numGumBalls;
state = NO_QUARTER;
}
public String toString() {
StringBuffer result = new StringBuffer();
result.append("Inventory: " + count + " gumball");
if (count != 1) {
result.append("s");
}
result.append("\nMachine is ");
if (state == SOLD_OUT) {
result.append("sold out");
} else if (state == NO_QUARTER) {
result.append("waiting for quarter");
} else if (state == HAS_QUARTER) {
result.append("waiting for turn of crank");
} else if (state == SOLD) {
result.append("delivering a gumball");
}
result.append("\n");
return result.toString();
}
}
测试类
public class GumballMachineTestDrive {
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(5);
//Inventory: 5 gumballs
//Machine is waiting for quarter
System.out.println(gumballMachine);
//You inserted a quarter
gumballMachine.insertQuarter();
//You can't insert another quarter
gumballMachine.insertQuarter();
//You turned...
//A gumball comes rolling out the slot
gumballMachine.turnCrank();
//Inventory: 4 gumballs
//Machine is waiting for quarter
System.out.println(gumballMachine);
}
}
需求发生变更,当曲柄被转动时,有10%的几率掉下来的是两颗糖果,多送一个,我们可以把状态定义成单独的类,并且实现共同的接口
实现如下
public interface State {
/*
* 定义状态类的接口
*/
//投币
public void insertQuarter();
//退币
public void ejectQuarter();
//转动曲柄
public void turnCrank();
//发放糖果
public void dispense();
}
public class HasQuarterState implements State {
Random randomWinner = new Random(System.currentTimeMillis());
GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public void insertQuarter() {
System.out.println("You can't insert another quarter");
}
public void ejectQuarter() {
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
public void turnCrank() {
System.out.println("You turned...");
//返回[0,10)之间均匀分布的int值
int winner = randomWinner.nextInt(10);
//只有糖果机至少有2个糖果时,才能变为幸运客户
if ((winner == 0) && (gumballMachine.getCount() > 1)) {
gumballMachine.setState(gumballMachine.getWinnerState());
} else {
gumballMachine.setState(gumballMachine.getSoldState());
}
}
public void dispense() {
System.out.println("No gumball dispensed");
}
public String toString() {
return "waiting for turn of crank";
}
}
public class WinnerState implements State {
GumballMachine gumballMachine;
public WinnerState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public void insertQuarter() {
System.out.println("Please wait, we're already giving you a Gumball");
}
public void ejectQuarter() {
System.out.println("Please wait, we're already giving you a Gumball");
}
public void turnCrank() {
System.out.println("Turning again doesn't get you another gumball!");
}
public void dispense() {
//这个是书上的代码,不修改了,感觉可以直接出两个糖果,没必要判断为零的情况,因为只有糖果机中的糖果数大于1时
//状态才有可能变为WinnerSate
System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter");
gumballMachine.releaseBall();
if (gumballMachine.getCount() == 0) {
gumballMachine.setState(gumballMachine.getSoldOutState());
} else {
gumballMachine.releaseBall();
if (gumballMachine.getCount() > 0) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
} else {
System.out.println("Oops, out of gumballs!");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}
public String toString() {
return "despensing two gumballs for your quarter, because YOU'RE A WINNER!";
}
}
机器类的代码更改为如下
public class GumballMachine {
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState;
State state = soldOutState;
int count = 0;
public GumballMachine(int numberGumballs) {
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
winnerState = new WinnerState(this);
this.count = numberGumballs;
if (numberGumballs > 0) {
state = noQuarterState;
}
}
public void insertQuarter() {
state.insertQuarter();
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void turnCrank() {
state.turnCrank();
state.dispense();
}
void setState(State state) {
this.state = state;
}
void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count = count - 1;
}
}
int getCount() {
return count;
}
void refill(int count) {
this.count = count;
state = noQuarterState;
}
public State getState() {
return state;
}
public State getSoldOutState() {
return soldOutState;
}
public State getNoQuarterState() {
return noQuarterState;
}
public State getHasQuarterState() {
return hasQuarterState;
}
public State getSoldState() {
return soldState;
}
public State getWinnerState() {
return winnerState;
}
public String toString() {
StringBuffer result = new StringBuffer();
result.append("\nInventory: " + count + " gumball");
if (count != 1) {
result.append("s");
}
result.append("\n");
result.append("Machine is " + state + "\n");
return result.toString();
}
}
测试类和上面类似,状态模式的类图
责任链模式
AbstractLogger.java
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level;
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger) {
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message) {
if (this.level <= level) {
write(message);
}
if (nextLogger != null) {
nextLogger.logMessage(level, message);
}
}
abstract protected void write (String message);
}
InfoLogger.java
public class InfoLogger extends AbstractLogger {
public InfoLogger(int level) {
this.level = level;
}
protected void write(String message) {
System.out.println("Ingo:Logger" + message);
}
}
DebugLogger.java
public class DebugLogger extends AbstractLogger {
public DebugLogger(int level) {
this.level = level;
}
protected void write(String message) {
System.out.println("Debug:Logger" + message);
}
}
ErrorLogger.java
public class ErrorLogger extends AbstractLogger {
public ErrorLogger(int level) {
this.level = level;
}
protected void write(String message) {
System.out.println("Error:Logger" + message);
}
}
ChainPatternDemo.java
public class ChainPatternDemo {
private static AbstractLogger getChainOfLoggers() {
InfoLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
DebugLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);
ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
errorLogger.setNextLogger(debugLogger);
debugLogger.setNextLogger(infoLogger);
return errorLogger;
}
public static void main(String[] args) {
AbstractLogger loggerChain = getChainOfLoggers();
//Ingo:Loggerinfo level
loggerChain.logMessage(AbstractLogger.INFO, "info level");
System.out.println();
//Debug:Loggerdebug level
//Ingo:Loggerdebug level
loggerChain.logMessage(AbstractLogger.DEBUG, "debug level");
System.out.println();
//Error:Loggererror level
//Debug:Loggererror level
//Ingo:Loggererror level
loggerChain.logMessage(AbstractLogger.ERROR, "error level");
}
}
参考博客:
责任链模式
[1]http://www.cnblogs.com/V1haoge/p/6530089.html
[2]http://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html