面向对象-设计模式-行为型

面向对象-设计模式-行为型算法

 

      日暮乡关何处是?烟波江上令人愁。express

 

简介:面向对象-设计模式-行为型。设计模式

1、概述

何谓设计模式框架

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、通过分类的、代码设计经验的总结。ide

设计模式的好处&学习目的学习

一、为了代码可重用行、让代码更易被他人理解、保证代码的可靠性、使代码编写真正实现工程化;ui

二、设计模式便于咱们维护项目,加强系统的健壮性和可扩展性;this

三、设计模式还能够锻炼码农的设计思惟、升华代码质量等。spa

2、行为型

责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式、空对象模式。设计

1. 责任链(Chain Of Responsibility)

Intent

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。

Class Diagram

  • Handler:定义处理请求的接口,而且实现后继链(successor)

Implementation

 1 public abstract class Handler {  2 
 3     protected Handler successor;  4 
 5 
 6     public Handler(Handler successor) {  7         this.successor = successor;  8  }  9 
10 
11     protected abstract void handleRequest(Request request); 12 }
View Code
 1 public class ConcreteHandler1 extends Handler {  2 
 3     public ConcreteHandler1(Handler successor) {  4         super(successor);  5  }  6 
 7 
 8  @Override  9     protected void handleRequest(Request request) { 10         if (request.getType() == RequestType.TYPE1) { 11             System.out.println(request.getName() + " is handle by ConcreteHandler1"); 12             return; 13  } 14         if (successor != null) { 15  successor.handleRequest(request); 16  } 17  } 18 }
View Code
 1 public class ConcreteHandler2 extends Handler {  2 
 3     public ConcreteHandler2(Handler successor) {  4         super(successor);  5  }  6 
 7 
 8  @Override  9     protected void handleRequest(Request request) { 10         if (request.getType() == RequestType.TYPE2) { 11             System.out.println(request.getName() + " is handle by ConcreteHandler2"); 12             return; 13  } 14         if (successor != null) { 15  successor.handleRequest(request); 16  } 17  } 18 }
View Code
 1 public class Request {  2 
 3     private RequestType type;  4     private String name;  5 
 6 
 7     public Request(RequestType type, String name) {  8         this.type = type;  9         this.name = name; 10  } 11 
12 
13     public RequestType getType() { 14         return type; 15  } 16 
17 
18     public String getName() { 19         return name; 20  } 21 }
View Code
1 public enum RequestType { 2  TYPE1, TYPE2 3 }
 1 public class Client {  2 
 3     public static void main(String[] args) {  4 
 5         Handler handler1 = new ConcreteHandler1(null);  6         Handler handler2 = new ConcreteHandler2(handler1);  7 
 8         Request request1 = new Request(RequestType.TYPE1, "request1");  9  handler2.handleRequest(request1); 10 
11         Request request2 = new Request(RequestType.TYPE2, "request2"); 12  handler2.handleRequest(request2); 13  } 14 }
View Code
1 输出: 2 request1 is handle by ConcreteHandler1 3 request2 is handle by ConcreteHandler2

2. 命令(Command)

Intent

将命令封装成对象中,具备如下做用:

  • 使用命令来参数化其它对象
  • 将命令放入队列中进行排队
  • 将命令的操做记录到日志中
  • 支持可撤销的操做

Class Diagram

  • Command:命令
  • Receiver:命令接收者,也就是命令真正的执行者
  • Invoker:经过它来调用命令
  • Client:能够设置命令与命令的接收者

Implementation

设计一个遥控器,能够控制电灯开关。

1 public interface Command { 2     void execute(); 3 }
 1 public class LightOnCommand implements Command {  2  Light light;  3 
 4     public LightOnCommand(Light light) {  5         this.light = light;  6  }  7 
 8  @Override  9     public void execute() { 10  light.on(); 11  } 12 }
View Code
 1 public class LightOffCommand implements Command {  2  Light light;  3 
 4     public LightOffCommand(Light light) {  5         this.light = light;  6  }  7 
 8  @Override  9     public void execute() { 10  light.off(); 11  } 12 }
View Code
 1 public class Light {  2 
 3     public void on() {  4         System.out.println("Light is on!");  5  }  6 
 7     public void off() {  8         System.out.println("Light is off!");  9  } 10 }
View Code
 1 /**
 2  * 遥控器  3  */
 4 public class Invoker {  5     private Command[] onCommands;  6     private Command[] offCommands;  7     private final int slotNum = 7;  8 
 9     public Invoker() { 10         this.onCommands = new Command[slotNum]; 11         this.offCommands = new Command[slotNum]; 12  } 13 
14     public void setOnCommand(Command command, int slot) { 15         onCommands[slot] = command; 16  } 17 
18     public void setOffCommand(Command command, int slot) { 19         offCommands[slot] = command; 20  } 21 
22     public void onButtonWasPushed(int slot) { 23  onCommands[slot].execute(); 24  } 25 
26     public void offButtonWasPushed(int slot) { 27  offCommands[slot].execute(); 28  } 29 }
View Code
 1 public class Client {  2     public static void main(String[] args) {  3         Invoker invoker = new Invoker();  4         Light light = new Light();  5         Command lightOnCommand = new LightOnCommand(light);  6         Command lightOffCommand = new LightOffCommand(light);  7         invoker.setOnCommand(lightOnCommand, 0);  8         invoker.setOffCommand(lightOffCommand, 0);  9         invoker.onButtonWasPushed(0); 10         invoker.offButtonWasPushed(0); 11  } 12 }

3. 解释器(Interpreter)

Intent

为语言建立解释器,一般由语言的语法和语法分析来定义。

Class Diagram

  • TerminalExpression:终结符表达式,每一个终结符都须要一个 TerminalExpression。
  • Context:上下文,包含解释器以外的一些全局信息。

Implementation

如下是一个规则检验器实现,具备 and 和 or 规则,经过规则能够构建一颗解析树,用来检验一个文本是否知足解析树定义的规则。

例如一颗解析树为 D And (A Or (B C)),文本 "D A" 知足该解析树定义的规则。

这里的 Context 指的是 String。

1 public abstract class Expression { 2     public abstract boolean interpret(String str); 3 }
 1 public class TerminalExpression extends Expression {  2 
 3     private String literal = null;  4 
 5     public TerminalExpression(String str) {  6         literal = str;  7  }  8 
 9     public boolean interpret(String str) { 10         StringTokenizer st = new StringTokenizer(str); 11         while (st.hasMoreTokens()) { 12             String test = st.nextToken(); 13             if (test.equals(literal)) { 14                 return true; 15  } 16  } 17         return false; 18  } 19 }
View Code
 1 public class AndExpression extends Expression {  2 
 3     private Expression expression1 = null;  4     private Expression expression2 = null;  5 
 6     public AndExpression(Expression expression1, Expression expression2) {  7         this.expression1 = expression1;  8         this.expression2 = expression2;  9  } 10 
11     public boolean interpret(String str) { 12         return expression1.interpret(str) && expression2.interpret(str); 13  } 14 }
View Code
 1 public class OrExpression extends Expression {  2     private Expression expression1 = null;  3     private Expression expression2 = null;  4 
 5     public OrExpression(Expression expression1, Expression expression2) {  6         this.expression1 = expression1;  7         this.expression2 = expression2;  8  }  9 
10     public boolean interpret(String str) { 11         return expression1.interpret(str) || expression2.interpret(str); 12  } 13 }
View Code
 1 public class Client {  2 
 3     /**
 4  * 构建解析树  5      */
 6     public static Expression buildInterpreterTree() {  7         // Literal
 8         Expression terminal1 = new TerminalExpression("A");  9         Expression terminal2 = new TerminalExpression("B"); 10         Expression terminal3 = new TerminalExpression("C"); 11         Expression terminal4 = new TerminalExpression("D"); 12         // B C
13         Expression alternation1 = new OrExpression(terminal2, terminal3); 14         // A Or (B C)
15         Expression alternation2 = new OrExpression(terminal1, alternation1); 16         // D And (A Or (B C))
17         return new AndExpression(terminal4, alternation2); 18  } 19 
20     public static void main(String[] args) { 21         Expression define = buildInterpreterTree(); 22         String context1 = "D A"; 23         String context2 = "A B"; 24         System.out.println(define.interpret(context1));  // true
25         System.out.println(define.interpret(context2));  // false
26  } 27 }
View Code

4. 迭代器(Iterator)

Intent

提供一种顺序访问聚合对象元素的方法,而且不暴露聚合对象的内部表示。

Class Diagram

  • Aggregate 是聚合类,其中 createIterator() 方法能够产生一个 Iterator;
  • Iterator 主要定义了 hasNext() 和 next() 方法;
  • Client 组合了 Aggregate,为了迭代遍历 Aggregate,也须要组合 Iterator。

Implementation

1 public interface Aggregate { 2  Iterator createIterator(); 3 }
 1 public class ConcreteAggregate implements Aggregate {  2 
 3     private Integer[] items;  4 
 5     public ConcreteAggregate() {  6         items = new Integer[10];  7         for (int i = 0; i < items.length; i++) {  8             items[i] = i;  9  } 10  } 11 
12  @Override 13     public Iterator createIterator() { 14         return new ConcreteIterator<Integer>(items); 15  } 16 }
View Code
1 public interface Iterator<Item> { 2  Item next(); 3     boolean hasNext(); 4 }
 1 public class ConcreteIterator<Item> implements Iterator {  2 
 3     private Item[] items;  4     private int position = 0;  5 
 6     public ConcreteIterator(Item[] items) {  7         this.items = items;  8  }  9 
10  @Override 11     public Object next() { 12         return items[position++]; 13  } 14 
15  @Override 16     public boolean hasNext() { 17         return position < items.length; 18  } 19 }
View Code
1 public class Client { 2     public static void main(String[] args) { 3         Aggregate aggregate = new ConcreteAggregate(); 4         Iterator<Integer> iterator = aggregate.createIterator(); 5         while (iterator.hasNext()) { 6  System.out.println(iterator.next()); 7  } 8  } 9 }

5. 中介者(Mediator)

Intent

集中相关对象之间复杂的沟通和控制方式。

Class Diagram

  • Mediator:中介者,定义一个接口用于与各同事(Colleague)对象通讯。
  • Colleague:同事,相关对象。

Implementation

Alarm(闹钟)、CoffeePot(咖啡壶)、Calendar(日历)、Sprinkler(喷头)是一组相关的对象,在某个对象的事件产生时须要去操做其它对象,造成了下面这种依赖结构:

使用中介者模式能够将复杂的依赖结构变成星形结构:

1 public abstract class Colleague { 2     public abstract void onEvent(Mediator mediator); 3 }
 1 public class Alarm extends Colleague {  2 
 3  @Override  4     public void onEvent(Mediator mediator) {  5         mediator.doEvent("alarm");  6  }  7 
 8     public void doAlarm() {  9         System.out.println("doAlarm()"); 10  } 11 }
View Code
 1 public class CoffeePot extends Colleague {  2  @Override  3     public void onEvent(Mediator mediator) {  4         mediator.doEvent("coffeePot");  5  }  6 
 7     public void doCoffeePot() {  8         System.out.println("doCoffeePot()");  9  } 10 }
View Code
 1 public class Calender extends Colleague {  2  @Override  3     public void onEvent(Mediator mediator) {  4         mediator.doEvent("calender");  5  }  6 
 7     public void doCalender() {  8         System.out.println("doCalender()");  9  } 10 }
View Code
 1 public class Sprinkler extends Colleague {  2  @Override  3     public void onEvent(Mediator mediator) {  4         mediator.doEvent("sprinkler");  5  }  6 
 7     public void doSprinkler() {  8         System.out.println("doSprinkler()");  9  } 10 }
View Code
1 public abstract class Mediator { 2     public abstract void doEvent(String eventType); 3 }
 1 public class ConcreteMediator extends Mediator {  2     private Alarm alarm;  3     private CoffeePot coffeePot;  4     private Calender calender;  5     private Sprinkler sprinkler;  6 
 7     public ConcreteMediator(Alarm alarm, CoffeePot coffeePot, Calender calender, Sprinkler sprinkler) {  8         this.alarm = alarm;  9         this.coffeePot = coffeePot; 10         this.calender = calender; 11         this.sprinkler = sprinkler; 12  } 13 
14  @Override 15     public void doEvent(String eventType) { 16         switch (eventType) { 17             case "alarm": 18  doAlarmEvent(); 19                 break; 20             case "coffeePot": 21  doCoffeePotEvent(); 22                 break; 23             case "calender": 24  doCalenderEvent(); 25                 break; 26             default: 27  doSprinklerEvent(); 28  } 29  } 30 
31     public void doAlarmEvent() { 32  alarm.doAlarm(); 33  coffeePot.doCoffeePot(); 34  calender.doCalender(); 35  sprinkler.doSprinkler(); 36  } 37 
38     public void doCoffeePotEvent() { 39         // ...
40  } 41 
42     public void doCalenderEvent() { 43         // ...
44  } 45 
46     public void doSprinklerEvent() { 47         // ...
48  } 49 }
View Code
 1 public class Client {  2     public static void main(String[] args) {  3         Alarm alarm = new Alarm();  4         CoffeePot coffeePot = new CoffeePot();  5         Calender calender = new Calender();  6         Sprinkler sprinkler = new Sprinkler();  7         Mediator mediator = new ConcreteMediator(alarm, coffeePot, calender, sprinkler);  8         // 闹钟事件到达,调用中介者就能够操做相关对象
 9  alarm.onEvent(mediator); 10  } 11 }
1 输出: 2 doAlarm() 3 doCoffeePot() 4 doCalender() 5 doSprinkler()

6. 备忘录(Memento)

Intent

在不违反封装的状况下得到对象的内部状态,从而在须要时能够将对象恢复到最初状态。

Class Diagram

  • Originator:原始对象
  • Caretaker:负责保存好备忘录
  • Memento:备忘录,存储原始对象的状态。备忘录实际上有两个接口,一个是提供给 Caretaker 的窄接口:它只能将备忘录传递给其它对象;一个是提供给 Originator 的宽接口,容许它访问到先前状态所需的全部数据。理想状况是只容许 Originator 访问本备忘录的内部状态。

Implementation

如下实现了一个简单计算器程序,能够输入两个值,而后计算这两个值的和。备忘录模式容许将这两个值存储起来,而后在某个时刻用存储的状态进行恢复。

 1 /**
 2  * Originator Interface  3  */
 4 public interface Calculator {  5 
 6     // Create Memento
 7  PreviousCalculationToCareTaker backupLastCalculation();  8 
 9     // setMemento
10     void restorePreviousCalculation(PreviousCalculationToCareTaker memento); 11 
12     int getCalculationResult(); 13 
14     void setFirstNumber(int firstNumber); 15 
16     void setSecondNumber(int secondNumber); 17 }
View Code
 1 /**
 2  * Originator Implementation  3  */
 4 public class CalculatorImp implements Calculator {  5 
 6     private int firstNumber;  7     private int secondNumber;  8 
 9  @Override 10     public PreviousCalculationToCareTaker backupLastCalculation() { 11         // create a memento object used for restoring two numbers
12         return new PreviousCalculationImp(firstNumber, secondNumber); 13  } 14 
15  @Override 16     public void restorePreviousCalculation(PreviousCalculationToCareTaker memento) { 17         this.firstNumber = ((PreviousCalculationToOriginator) memento).getFirstNumber(); 18         this.secondNumber = ((PreviousCalculationToOriginator) memento).getSecondNumber(); 19  } 20 
21  @Override 22     public int getCalculationResult() { 23         // result is adding two numbers
24         return firstNumber + secondNumber; 25  } 26 
27  @Override 28     public void setFirstNumber(int firstNumber) { 29         this.firstNumber = firstNumber; 30  } 31 
32  @Override 33     public void setSecondNumber(int secondNumber) { 34         this.secondNumber = secondNumber; 35  } 36 }
View Code
1 /**
2  * Memento Interface to Originator 3  * 4  * This interface allows the originator to restore its state 5  */
6 public interface PreviousCalculationToOriginator { 7     int getFirstNumber(); 8     int getSecondNumber(); 9 }
1 /**
2  * Memento interface to CalculatorOperator (Caretaker) 3  */
4 public interface PreviousCalculationToCareTaker { 5     // no operations permitted for the caretaker
6 }
 1 /**
 2  * Memento Object Implementation  3  * <p>  4  * Note that this object implements both interfaces to Originator and CareTaker  5  */
 6 public class PreviousCalculationImp implements PreviousCalculationToCareTaker,  7  PreviousCalculationToOriginator {  8 
 9     private int firstNumber; 10     private int secondNumber; 11 
12     public PreviousCalculationImp(int firstNumber, int secondNumber) { 13         this.firstNumber = firstNumber; 14         this.secondNumber = secondNumber; 15  } 16 
17  @Override 18     public int getFirstNumber() { 19         return firstNumber; 20  } 21 
22  @Override 23     public int getSecondNumber() { 24         return secondNumber; 25  } 26 }
View Code
 1 /**
 2  * CareTaker object  3  */
 4 public class Client {  5 
 6     public static void main(String[] args) {  7         // program starts
 8         Calculator calculator = new CalculatorImp();  9 
10         // assume user enters two numbers
11         calculator.setFirstNumber(10); 12         calculator.setSecondNumber(100); 13 
14         // find result
15  System.out.println(calculator.getCalculationResult()); 16 
17         // Store result of this calculation in case of error
18         PreviousCalculationToCareTaker memento = calculator.backupLastCalculation(); 19 
20         // user enters a number
21         calculator.setFirstNumber(17); 22 
23         // user enters a wrong second number and calculates result
24         calculator.setSecondNumber(-290); 25 
26         // calculate result
27  System.out.println(calculator.getCalculationResult()); 28 
29         // user hits CTRL + Z to undo last operation and see last result
30  calculator.restorePreviousCalculation(memento); 31 
32         // result restored
33  System.out.println(calculator.getCalculationResult()); 34  } 35 }
View Code
1 输出: 2 110
3 -273
4 110

7. 观察者(Observer)

Intent

定义对象之间的一对多依赖,当一个对象状态改变时,它的全部依赖都会收到通知而且自动更新状态。

主题(Subject)是被观察的对象,而其全部依赖者(Observer)称为观察者。

Class Diagram

主题(Subject)具备注册和移除观察者、并通知全部观察者的功能,主题是经过维护一张观察者列表来实现这些操做的。

观察者(Observer)的注册功能须要调用主题的 registerObserver() 方法。

Implementation

天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,而且在未来会继续增长。

1 public interface Subject { 2     void registerObserver(Observer o); 3 
4     void removeObserver(Observer o); 5 
6     void notifyObserver(); 7 }
 1 public class WeatherData implements Subject {  2     private List<Observer> observers;  3     private float temperature;  4     private float humidity;  5     private float pressure;  6 
 7     public WeatherData() {  8         observers = new ArrayList<>();  9  } 10 
11     public void setMeasurements(float temperature, float humidity, float pressure) { 12         this.temperature = temperature; 13         this.humidity = humidity; 14         this.pressure = pressure; 15  notifyObserver(); 16  } 17 
18  @Override 19     public void registerObserver(Observer o) { 20  observers.add(o); 21  } 22 
23  @Override 24     public void removeObserver(Observer o) { 25         int i = observers.indexOf(o); 26         if (i >= 0) { 27  observers.remove(i); 28  } 29  } 30 
31  @Override 32     public void notifyObserver() { 33         for (Observer o : observers) { 34  o.update(temperature, humidity, pressure); 35  } 36  } 37 }
View Code
1 public interface Observer { 2     void update(float temp, float humidity, float pressure); 3 }
 1 public class StatisticsDisplay implements Observer {  2 
 3     public StatisticsDisplay(Subject weatherData) {  4         weatherData.registerObserver(this);  5  }  6 
 7  @Override  8     public void update(float temp, float humidity, float pressure) {  9         System.out.println("StatisticsDisplay.update: " + temp + " " + humidity + " " + pressure); 10  } 11 }
View Code
 1 public class CurrentConditionsDisplay implements Observer {  2 
 3     public CurrentConditionsDisplay(Subject weatherData) {  4         weatherData.registerObserver(this);  5  }  6 
 7  @Override  8     public void update(float temp, float humidity, float pressure) {  9         System.out.println("CurrentConditionsDisplay.update: " + temp + " " + humidity + " " + pressure); 10  } 11 }
View Code
 1 public class WeatherStation {  2     public static void main(String[] args) {  3         WeatherData weatherData = new WeatherData();  4         CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);  5         StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);  6 
 7         weatherData.setMeasurements(0, 0, 0);  8         weatherData.setMeasurements(1, 1, 1);  9  } 10 }
1 输出: 2 CurrentConditionsDisplay.update: 0.0 0.0 0.0
3 StatisticsDisplay.update: 0.0 0.0 0.0
4 CurrentConditionsDisplay.update: 1.0 1.0 1.0
5 StatisticsDisplay.update: 1.0 1.0 1.0

8. 状态(State)

Intent

容许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。

Class Diagram

Implementation

糖果销售机有多种状态,每种状态下销售机有不一样的行为,状态能够发生转移,使得销售机的行为也发生改变。

 1 public interface State {  2     /**
 3  * 投入 25 分钱  4      */
 5     void insertQuarter();  6 
 7     /**
 8  * 退回 25 分钱  9      */
10     void ejectQuarter(); 11 
12     /**
13  * 转动曲柄 14      */
15     void turnCrank(); 16 
17     /**
18  * 发放糖果 19      */
20     void dispense(); 21 }
 1 public class HasQuarterState implements State {  2 
 3     private GumballMachine gumballMachine;  4 
 5     public HasQuarterState(GumballMachine gumballMachine) {  6         this.gumballMachine = gumballMachine;  7  }  8 
 9  @Override 10     public void insertQuarter() { 11         System.out.println("You can't insert another quarter"); 12  } 13 
14  @Override 15     public void ejectQuarter() { 16         System.out.println("Quarter returned"); 17  gumballMachine.setState(gumballMachine.getNoQuarterState()); 18  } 19 
20  @Override 21     public void turnCrank() { 22         System.out.println("You turned..."); 23  gumballMachine.setState(gumballMachine.getSoldState()); 24  } 25 
26  @Override 27     public void dispense() { 28         System.out.println("No gumball dispensed"); 29  } 30 }
View Code
 1 public class NoQuarterState implements State {  2 
 3  GumballMachine gumballMachine;  4 
 5     public NoQuarterState(GumballMachine gumballMachine) {  6         this.gumballMachine = gumballMachine;  7  }  8 
 9  @Override 10     public void insertQuarter() { 11         System.out.println("You insert a quarter"); 12  gumballMachine.setState(gumballMachine.getHasQuarterState()); 13  } 14 
15  @Override 16     public void ejectQuarter() { 17         System.out.println("You haven't insert a quarter"); 18  } 19 
20  @Override 21     public void turnCrank() { 22         System.out.println("You turned, but there's no quarter"); 23  } 24 
25  @Override 26     public void dispense() { 27         System.out.println("You need to pay first"); 28  } 29 }
View Code
 1 public class SoldOutState implements State {  2 
 3  GumballMachine gumballMachine;  4 
 5     public SoldOutState(GumballMachine gumballMachine) {  6         this.gumballMachine = gumballMachine;  7  }  8 
 9  @Override 10     public void insertQuarter() { 11         System.out.println("You can't insert a quarter, the machine is sold out"); 12  } 13 
14  @Override 15     public void ejectQuarter() { 16         System.out.println("You can't eject, you haven't inserted a quarter yet"); 17  } 18 
19  @Override 20     public void turnCrank() { 21         System.out.println("You turned, but there are no gumballs"); 22  } 23 
24  @Override 25     public void dispense() { 26         System.out.println("No gumball dispensed"); 27  } 28 }
View Code
 1 public class SoldState implements State {  2 
 3  GumballMachine gumballMachine;  4 
 5     public SoldState(GumballMachine gumballMachine) {  6         this.gumballMachine = gumballMachine;  7  }  8 
 9  @Override 10     public void insertQuarter() { 11         System.out.println("Please wait, we're already giving you a gumball"); 12  } 13 
14  @Override 15     public void ejectQuarter() { 16         System.out.println("Sorry, you already turned the crank"); 17  } 18 
19  @Override 20     public void turnCrank() { 21         System.out.println("Turning twice doesn't get you another gumball!"); 22  } 23 
24  @Override 25     public void dispense() { 26  gumballMachine.releaseBall(); 27         if (gumballMachine.getCount() > 0) { 28  gumballMachine.setState(gumballMachine.getNoQuarterState()); 29         } else { 30             System.out.println("Oops, out of gumballs"); 31  gumballMachine.setState(gumballMachine.getSoldOutState()); 32  } 33  } 34 }
View Code
 1 public class GumballMachine {  2 
 3     private State soldOutState;  4     private State noQuarterState;  5     private State hasQuarterState;  6     private State soldState;  7 
 8     private State state;  9     private int count = 0; 10 
11     public GumballMachine(int numberGumballs) { 12         count = numberGumballs; 13         soldOutState = new SoldOutState(this); 14         noQuarterState = new NoQuarterState(this); 15         hasQuarterState = new HasQuarterState(this); 16         soldState = new SoldState(this); 17 
18         if (numberGumballs > 0) { 19             state = noQuarterState; 20         } else { 21             state = soldOutState; 22  } 23  } 24 
25     public void insertQuarter() { 26  state.insertQuarter(); 27  } 28 
29     public void ejectQuarter() { 30  state.ejectQuarter(); 31  } 32 
33     public void turnCrank() { 34  state.turnCrank(); 35  state.dispense(); 36  } 37 
38     public void setState(State state) { 39         this.state = state; 40  } 41 
42     public void releaseBall() { 43         System.out.println("A gumball comes rolling out the slot..."); 44         if (count != 0) { 45             count -= 1; 46  } 47  } 48 
49     public State getSoldOutState() { 50         return soldOutState; 51  } 52 
53     public State getNoQuarterState() { 54         return noQuarterState; 55  } 56 
57     public State getHasQuarterState() { 58         return hasQuarterState; 59  } 60 
61     public State getSoldState() { 62         return soldState; 63  } 64 
65     public int getCount() { 66         return count; 67  } 68 }
View Code
 1 public class Client {  2 
 3     public static void main(String[] args) {  4         GumballMachine gumballMachine = new GumballMachine(5);  5 
 6  gumballMachine.insertQuarter();  7  gumballMachine.turnCrank();  8 
 9  gumballMachine.insertQuarter(); 10  gumballMachine.ejectQuarter(); 11  gumballMachine.turnCrank(); 12 
13  gumballMachine.insertQuarter(); 14  gumballMachine.turnCrank(); 15  gumballMachine.insertQuarter(); 16  gumballMachine.turnCrank(); 17  gumballMachine.ejectQuarter(); 18 
19  gumballMachine.insertQuarter(); 20  gumballMachine.insertQuarter(); 21  gumballMachine.turnCrank(); 22  gumballMachine.insertQuarter(); 23  gumballMachine.turnCrank(); 24  gumballMachine.insertQuarter(); 25  gumballMachine.turnCrank(); 26  } 27 }
View Code
 1 输出:  2 You insert a quarter  3 You turned...  4 A gumball comes rolling out the slot...  5 You insert a quarter  6 Quarter returned  7 You turned, but there's no quarter
 8 You need to pay first  9 You insert a quarter 10 You turned... 11 A gumball comes rolling out the slot... 12 You insert a quarter 13 You turned... 14 A gumball comes rolling out the slot... 15 You haven't insert a quarter
16 You insert a quarter 17 You can't insert another quarter
18 You turned... 19 A gumball comes rolling out the slot... 20 You insert a quarter 21 You turned... 22 A gumball comes rolling out the slot... 23 Oops, out of gumballs 24 You can't insert a quarter, the machine is sold out
25 You turned, but there are no gumballs 26 No gumball dispensed

9. 策略(Strategy)

Intent

定义一系列算法,封装每一个算法,并使它们能够互换。

策略模式可让算法独立于使用它的客户端。

Class Diagram

  • Strategy 接口定义了一个算法族,它们都实现了 behavior() 方法。
  • Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法能够动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。

与状态模式的比较

状态模式的类图和策略模式相似,而且都是可以动态改变对象的行为。可是状态模式是经过状态转移来改变 Context 所组合的 State 对象,而策略模式是经过 Context 自己的决策来改变组合的 Strategy 对象。所谓的状态转移,是指 Context 在运行过程当中因为一些条件发生改变而使得 State 对象发生改变,注意必需要是在运行过程当中。

状态模式主要是用来解决状态转移的问题,当状态发生转移了,那么 Context 对象就会改变它的行为;而策略模式主要是用来封装一组能够互相替代的算法族,而且能够根据须要动态地去替换 Context 使用的算法。

Implementation

设计一个鸭子,它能够动态地改变叫声。这里的算法族是鸭子的叫声行为。

1 public interface QuackBehavior { 2     void quack(); 3 }
1 public class Quack implements QuackBehavior { 2  @Override 3     public void quack() { 4         System.out.println("quack!"); 5  } 6 }
1 public class Squeak implements QuackBehavior{ 2  @Override 3     public void quack() { 4         System.out.println("squeak!"); 5  } 6 }
 1 public class Duck {  2 
 3     private QuackBehavior quackBehavior;  4 
 5     public void performQuack() {  6         if (quackBehavior != null) {  7  quackBehavior.quack();  8  }  9  } 10 
11     public void setQuackBehavior(QuackBehavior quackBehavior) { 12         this.quackBehavior = quackBehavior; 13  } 14 }
View Code
 1 public class Client {  2 
 3     public static void main(String[] args) {  4         Duck duck = new Duck();  5         duck.setQuackBehavior(new Squeak());  6  duck.performQuack();  7         duck.setQuackBehavior(new Quack());  8  duck.performQuack();  9  } 10 }
1 输出: 2 squeak!
3 quack!

10. 模板方法(Template Method)

Intent

定义算法框架,并将一些步骤的实现延迟到子类。

经过模板方法,子类能够从新定义算法的某些步骤,而不用改变算法的结构。

Class Diagram

Implementation

冲咖啡和冲茶都有相似的流程,可是某些步骤会有点不同,要求复用那些相同步骤的代码。

 1 public abstract class CaffeineBeverage {  2 
 3     final void prepareRecipe() {  4  boilWater();  5  brew();  6  pourInCup();  7  addCondiments();  8  }  9 
10     abstract void brew(); 11 
12     abstract void addCondiments(); 13 
14     void boilWater() { 15         System.out.println("boilWater"); 16  } 17 
18     void pourInCup() { 19         System.out.println("pourInCup"); 20  } 21 }
 1 public class Coffee extends CaffeineBeverage {  2  @Override  3     void brew() {  4         System.out.println("Coffee.brew");  5  }  6 
 7  @Override  8     void addCondiments() {  9         System.out.println("Coffee.addCondiments"); 10  } 11 }
 1 public class Tea extends CaffeineBeverage {  2  @Override  3     void brew() {  4         System.out.println("Tea.brew");  5  }  6 
 7  @Override  8     void addCondiments() {  9         System.out.println("Tea.addCondiments"); 10  } 11 }
1 public class Client { 2     public static void main(String[] args) { 3         CaffeineBeverage caffeineBeverage = new Coffee(); 4  caffeineBeverage.prepareRecipe(); 5         System.out.println("-----------"); 6         caffeineBeverage = new Tea(); 7  caffeineBeverage.prepareRecipe(); 8  } 9 }
 1 输出:  2 boilWater  3 Coffee.brew  4 pourInCup  5 Coffee.addCondiments  6 -----------
 7 boilWater  8 Tea.brew  9 pourInCup 10 Tea.addCondiments

11. 访问者(Visitor)

Intent

为一个对象结构(好比组合结构)增长新能力。

Class Diagram

  • Visitor:访问者,为每个 ConcreteElement 声明一个 visit 操做
  • ConcreteVisitor:具体访问者,存储遍历过程当中的累计结果
  • ObjectStructure:对象结构,能够是组合结构,或者是一个集合。

Implementation

1 public interface Element { 2     void accept(Visitor visitor); 3 }
 1 class CustomerGroup {  2 
 3     private List<Customer> customers = new ArrayList<>();  4 
 5     void accept(Visitor visitor) {  6         for (Customer customer : customers) {  7  customer.accept(visitor);  8  }  9  } 10 
11     void addCustomer(Customer customer) { 12  customers.add(customer); 13  } 14 }
View Code
 1 public class Customer implements Element {  2 
 3     private String name;  4     private List<Order> orders = new ArrayList<>();  5 
 6  Customer(String name) {  7         this.name = name;  8  }  9 
10  String getName() { 11         return name; 12  } 13 
14     void addOrder(Order order) { 15  orders.add(order); 16  } 17 
18     public void accept(Visitor visitor) { 19         visitor.visit(this); 20         for (Order order : orders) { 21  order.accept(visitor); 22  } 23  } 24 }
View Code
 1 public class Order implements Element {  2 
 3     private String name;  4     private List<Item> items = new ArrayList();  5 
 6  Order(String name) {  7         this.name = name;  8  }  9 
10  Order(String name, String itemName) { 11         this.name = name; 12         this.addItem(new Item(itemName)); 13  } 14 
15  String getName() { 16         return name; 17  } 18 
19     void addItem(Item item) { 20  items.add(item); 21  } 22 
23     public void accept(Visitor visitor) { 24         visitor.visit(this); 25 
26         for (Item item : items) { 27  item.accept(visitor); 28  } 29  } 30 }
View Code
 1 public class Item implements Element {  2 
 3     private String name;  4 
 5  Item(String name) {  6         this.name = name;  7  }  8 
 9  String getName() { 10         return name; 11  } 12 
13     public void accept(Visitor visitor) { 14         visitor.visit(this); 15  } 16 }
View Code
1 public interface Visitor { 2     void visit(Customer customer); 3 
4     void visit(Order order); 5 
6     void visit(Item item); 7 }
 1 public class GeneralReport implements Visitor {  2 
 3     private int customersNo;  4     private int ordersNo;  5     private int itemsNo;  6 
 7     public void visit(Customer customer) {  8  System.out.println(customer.getName());  9         customersNo++; 10  } 11 
12     public void visit(Order order) { 13  System.out.println(order.getName()); 14         ordersNo++; 15  } 16 
17     public void visit(Item item) { 18  System.out.println(item.getName()); 19         itemsNo++; 20  } 21 
22     public void displayResults() { 23         System.out.println("Number of customers: " + customersNo); 24         System.out.println("Number of orders:    " + ordersNo); 25         System.out.println("Number of items:     " + itemsNo); 26  } 27 }
View Code
 1 public class Client {  2     public static void main(String[] args) {  3         Customer customer1 = new Customer("customer1");  4         customer1.addOrder(new Order("order1", "item1"));  5         customer1.addOrder(new Order("order2", "item1"));  6         customer1.addOrder(new Order("order3", "item1"));  7 
 8         Order order = new Order("order_a");  9         order.addItem(new Item("item_a1")); 10         order.addItem(new Item("item_a2")); 11         order.addItem(new Item("item_a3")); 12         Customer customer2 = new Customer("customer2"); 13  customer2.addOrder(order); 14 
15         CustomerGroup customers = new CustomerGroup(); 16  customers.addCustomer(customer1); 17  customers.addCustomer(customer2); 18 
19         GeneralReport visitor = new GeneralReport(); 20  customers.accept(visitor); 21  visitor.displayResults(); 22  } 23 }
View Code
 1 输出:  2 customer1  3 order1  4 item1  5 order2  6 item1  7 order3  8 item1  9 customer2 10 order_a 11 item_a1 12 item_a2 13 item_a3 14 Number of customers: 2
15 Number of orders:    4
16 Number of items:     6

12. 空对象(Null)

Intent

使用什么都不作的空对象来代替 NULL。

一个方法返回 NULL,意味着方法的调用端须要去检查返回值是不是 NULL,这么作会致使很是多的冗余的检查代码。而且若是某一个调用端忘记了作这个检查返回值,而直接使用返回的对象,那么就有可能抛出空指针异常。

Class Diagram

Implementation

1 public abstract class AbstractOperation { 2     abstract void request(); 3 }
1 public class RealOperation extends AbstractOperation { 2  @Override 3     void request() { 4         System.out.println("do something"); 5  } 6 }
1 public class NullOperation extends AbstractOperation{ 2  @Override 3     void request() { 4         // do nothing
5  } 6 }
 1 public class Client {  2     public static void main(String[] args) {  3         AbstractOperation abstractOperation = func(-1);  4  abstractOperation.request();  5  }  6 
 7     public static AbstractOperation func(int para) {  8         if (para < 0) {  9             return new NullOperation(); 10  } 11         return new RealOperation(); 12  } 13 }
View Code

 

 

 

日暮乡关何处是?

        烟波江上令人愁

相关文章
相关标签/搜索