| 模式 & 描述 | 包括 |
|---|---|
| 行为型模式 这些设计模式特别关注对象之间的通信。 | 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) |
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。

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);}
ConsoleLogger.java
public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level){this.level = level;}@Overrideprotected void write(String message) { System.out.println("Standard Console::Logger: " + message);}
}
ErrorLogger.java
public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level){this.level = level;}@Overrideprotected void write(String message) { System.out.println("Error Console::Logger: " + message);}
}
FileLogger.java
public class FileLogger extends AbstractLogger {public FileLogger(int level){this.level = level;}@Overrideprotected void write(String message) { System.out.println("File::Logger: " + message);}
}
创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
ChainPatternDemo.java
public class ChainPatternDemo {private static AbstractLogger getChainOfLoggers(){AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger; }public static void main(String[] args) {AbstractLogger loggerChain = getChainOfLoggers();loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");}
}
Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
命令模式结构示意图:

我们首先创建作为命令的接口 Order,然后创建作为请求的 Stock 类。实体命令类 BuyStock 和 SellStock,实现了 Order 接口,将执行实际的命令处理。创建作为调用对象的类 Broker,它接受订单并能下订单。
Broker 对象使用命令模式,基于命令的类型确定哪个对象执行哪个命令。CommandPatternDemo 类使用 Broker 类来演示命令模式。

Order.java
public interface Order {void execute();
}
Stock.java
public class Stock {private String name = "ABC";private int quantity = 10;public void buy(){System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] bought");}public void sell(){System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] sold");}
}
BuyStock.java
public class BuyStock implements Order {private Stock abcStock;public BuyStock(Stock abcStock){this.abcStock = abcStock;}public void execute() {abcStock.buy();}
}
SellStock.java
public class SellStock implements Order {private Stock abcStock;public SellStock(Stock abcStock){this.abcStock = abcStock;}public void execute() {abcStock.sell();}
}
Broker.java
import java.util.ArrayList;
import java.util.List;public class Broker {private List orderList = new ArrayList(); public void takeOrder(Order order){orderList.add(order); }public void placeOrders(){for (Order order : orderList) {order.execute();}orderList.clear();}
}
CommandPatternDemo.java
public class CommandPatternDemo {public static void main(String[] args) {Stock abcStock = new Stock();BuyStock buyStockOrder = new BuyStock(abcStock);SellStock sellStockOrder = new SellStock(abcStock);Broker broker = new Broker();broker.takeOrder(buyStockOrder);broker.takeOrder(sellStockOrder);broker.placeOrders();}
}
Stock [ Name: ABC, Quantity: 10 ] bought
Stock [ Name: ABC, Quantity: 10 ] sold
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
我们将创建一个接口 Expression 和实现了 Expression 接口的实体类。定义作为上下文中主要解释器的 TerminalExpression 类。其他的类 OrExpression、AndExpression 用于创建组合式表达式。
InterpreterPatternDemo,我们的演示类使用 Expression 类创建规则和演示表达式的解析。

Expression.java
public interface Expression {public boolean interpret(String context);
}
TerminalExpression.java
public class TerminalExpression implements Expression {private String data;public TerminalExpression(String data){this.data = data; }@Overridepublic boolean interpret(String context) {if(context.contains(data)) {return true;}return false;}
}
OrExpression.java
public class OrExpression implements Expression {private Expression expr1 = null;private Expression expr2 = null;public OrExpression(Expression expr1, Expression expr2) { this.expr1 = expr1;this.expr2 = expr2;}@Overridepublic boolean interpret(String context) { return expr1.interpret(context) || expr2.interpret(context);}
}
AndExpression.java
public class AndExpression implements Expression {private Expression expr1 = null;private Expression expr2 = null;public AndExpression(Expression expr1, Expression expr2) { this.expr1 = expr1;this.expr2 = expr2;}@Overridepublic boolean interpret(String context) { return expr1.interpret(context) && expr2.interpret(context);}
}
InterpreterPatternDemo.java
public class InterpreterPatternDemo {//规则:Robert 和 John 是男性public static Expression getMaleExpression(){Expression robert = new TerminalExpression("Robert");Expression john = new TerminalExpression("John");return new OrExpression(robert, john); }//规则:Julie 是一个已婚的女性public static Expression getMarriedWomanExpression(){Expression julie = new TerminalExpression("Julie");Expression married = new TerminalExpression("Married");return new AndExpression(julie, married); }public static void main(String[] args) {Expression isMale = getMaleExpression();Expression isMarriedWoman = getMarriedWomanExpression();System.out.println("John is male? " + isMale.interpret("John"));System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie"));}
}
John is male? true
Julie is a married women? true
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
迭代器模式属于行为型模式。
我们将创建一个叙述导航方法的 Iterator 接口和一个返回迭代器的 Container 接口。实现了 Container 接口的实体类将负责实现 Iterator 接口。
IteratorPatternDemo,我们的演示类使用实体类 NamesRepository 来打印 NamesRepository 中存储为集合的 Names

Iterator.java
public interface Iterator {public boolean hasNext();public Object next();
}
Container.java
public interface Container {public Iterator getIterator();
}
NameRepository.java
public class NameRepository implements Container {public String[] names = {"Robert" , "John" ,"Julie" , "Lora"};@Overridepublic Iterator getIterator() {return new NameIterator();}private class NameIterator implements Iterator {int index;@Overridepublic boolean hasNext() {if(index < names.length){return true;}return false;}@Overridepublic Object next() {if(this.hasNext()){return names[index++];}return null;} }
}
IteratorPatternDemo.java
public class IteratorPatternDemo {public static void main(String[] args) {NameRepository namesRepository = new NameRepository();for(Iterator iter = namesRepository.getIterator(); iter.hasNext(); ){String name = (String)iter.next();System.out.println("Name : " + name);} }
}
Name : Robert
Name : John
Name : Julie
Name : Lora
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
我们通过聊天室实例来演示中介者模式。实例中,多个用户可以向聊天室发送消息,聊天室向所有的用户显示消息。我们将创建两个类 ChatRoom 和 User。User 对象使用 ChatRoom 方法来分享他们的消息。
MediatorPatternDemo,我们的演示类使用 User 对象来显示他们之间的通信。

ChatRoom.java
import java.util.Date;public class ChatRoom {public static void showMessage(User user, String message){System.out.println(new Date().toString() + " [" + user.getName() +"] : " + message);}
}
User.java
public class User {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public User(String name){this.name = name;}public void sendMessage(String message){ChatRoom.showMessage(this, message);}
}
MediatorPatternDemo.java
public class MediatorPatternDemo {public static void main(String[] args) {User robert = new User("Robert");User john = new User("John");robert.sendMessage("Hi! John!");john.sendMessage("Hello! Robert!");}
}
Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
备忘录模式使用三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。
MementoPatternDemo,我们的演示类使用 CareTaker 和 Originator 对象来显示对象的状态恢复。

Memento.java
public class Memento {private String state;public Memento(String state){this.state = state;}public String getState(){return state;}
}
Originator.java
public class Originator {private String state;public void setState(String state){this.state = state;}public String getState(){return state;}public Memento saveStateToMemento(){return new Memento(state);}public void getStateFromMemento(Memento Memento){state = Memento.getState();}
}
CareTaker.java
import java.util.ArrayList;
import java.util.List;public class CareTaker {private List mementoList = new ArrayList();public void add(Memento state){mementoList.add(state);}public Memento get(int index){return mementoList.get(index);}
}
MementoPatternDemo.java
public class MementoPatternDemo {public static void main(String[] args) {Originator originator = new Originator();CareTaker careTaker = new CareTaker();originator.setState("State #1");originator.setState("State #2");careTaker.add(originator.saveStateToMemento());originator.setState("State #3");careTaker.add(originator.saveStateToMemento());originator.setState("State #4");System.out.println("Current State: " + originator.getState()); originator.getStateFromMemento(careTaker.get(0));System.out.println("First saved State: " + originator.getState());originator.getStateFromMemento(careTaker.get(1));System.out.println("Second saved State: " + originator.getState());}
}
Current State: State #4
First saved State: State #2
Second saved State: State #3
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。
ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。

Subject.java
import java.util.ArrayList;
import java.util.List;public class Subject {private List observers = new ArrayList();private int state;public int getState() {return state;}public void setState(int state) {this.state = state;notifyAllObservers();}public void attach(Observer observer){observers.add(observer); }public void notifyAllObservers(){for (Observer observer : observers) {observer.update();}}
}
Observer.java
public abstract class Observer {protected Subject subject;public abstract void update();
}
BinaryObserver.java
public class BinaryObserver extends Observer{public BinaryObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); }
}
OctalObserver.java
public class OctalObserver extends Observer{public OctalObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); }
}
HexaObserver.java
public class HexaObserver extends Observer{public HexaObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); }
}
ObserverPatternDemo.java
public class ObserverPatternDemo {public static void main(String[] args) {Subject subject = new Subject();new HexaObserver(subject);new OctalObserver(subject);new BinaryObserver(subject);System.out.println("First state change: 15"); subject.setState(15);System.out.println("Second state change: 10"); subject.setState(10);}
}
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
我们将创建一个 State 接口和实现了 State 接口的实体状态类。Context 是一个带有某个状态的类。
StatePatternDemo,我们的演示类使用 Context 和状态对象来演示 Context 在状态改变时的行为变化。

State.java
public interface State {public void doAction(Context context);
}
StartState.java
public class StartState implements State {public void doAction(Context context) {System.out.println("Player is in start state");context.setState(this); }public String toString(){return "Start State";}
}
StopState.java
public class StopState implements State {public void doAction(Context context) {System.out.println("Player is in stop state");context.setState(this); }public String toString(){return "Stop State";}
}
Context.java
public class Context {private State state;public Context() {state = null;}public void setState(State state) {this.state = state; }public State getState() {return state;}
}
StatePatternDemo.java
public class StatePatternDemo {public static void main(String[] args) {Context context = new Context();StartState startState = new StartState();startState.doAction(context);System.out.println(context.getState().toString());StopState stopState = new StopState();stopState.doAction(context);System.out.println(context.getState().toString());}
}
Player is in start state
Start State
Player is in stop state
Stop State
在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。
在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。
我们将创建一个定义操作(在这里,是客户的名称)的 AbstractCustomer 抽象类,和扩展了 AbstractCustomer 类的实体类。工厂类 CustomerFactory 基于客户传递的名字来返回 RealCustomer 或 NullCustomer 对象。
NullPatternDemo,我们的演示类使用 CustomerFactory 来演示空对象模式的用法。

AbstractCustomer.java
public abstract class AbstractCustomer {protected String name;public abstract boolean isNil();public abstract String getName();
}
RealCustomer.java
public class RealCustomer extends AbstractCustomer {public RealCustomer(String name) {this.name = name; }@Overridepublic String getName() {return name;}@Overridepublic boolean isNil() {return false;}
}
NullCustomer.java
public class NullCustomer extends AbstractCustomer {@Overridepublic String getName() {return "Not Available in Customer Database";}@Overridepublic boolean isNil() {return true;}
}
CustomerFactory.java
public class CustomerFactory {public static final String[] names = {"Rob", "Joe", "Julie"};public static AbstractCustomer getCustomer(String name){for (int i = 0; i < names.length; i++) {if (names[i].equalsIgnoreCase(name)){return new RealCustomer(name);}}return new NullCustomer();}
}
NullPatternDemo.java
public class NullPatternDemo {public static void main(String[] args) {AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob");AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob");AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie");AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura");System.out.println("Customers");System.out.println(customer1.getName());System.out.println(customer2.getName());System.out.println(customer3.getName());System.out.println(customer4.getName());}
}
Customers
Rob
Not Available in Customer Database
Julie
Not Available in Customer Database
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
我们将创建一个定义活动的 Strategy 接口和实现了 Strategy 接口的实体策略类。Context 是一个使用了某种策略的类。
StrategyPatternDemo,我们的演示类使用 Context 和策略对象来演示 Context 在它所配置或使用的策略改变时的行为变化。

Strategy.java
public interface Strategy {public int doOperation(int num1, int num2);
}
OperationAdd.java
public class OperationAdd implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 + num2;}
}
OperationSubtract.java
public class OperationSubtract implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}
}
OperationMultiply.java
public class OperationMultiply implements Strategy{@Overridepublic int doOperation(int num1, int num2) {return num1 * num2;}
}
Context.java
public class Context {private Strategy strategy;public Context(Strategy strategy){this.strategy = strategy;}public int executeStrategy(int num1, int num2){return strategy.doOperation(num1, num2);}
}
StrategyPatternDemo.java
public class StrategyPatternDemo {public static void main(String[] args) {Context context = new Context(new OperationAdd()); System.out.println("10 + 5 = " + context.executeStrategy(10, 5));context = new Context(new OperationSubtract()); System.out.println("10 - 5 = " + context.executeStrategy(10, 5));context = new Context(new OperationMultiply()); System.out.println("10 * 5 = " + context.executeStrategy(10, 5));}
}
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
我们将创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法。
TemplatePatternDemo,我们的演示类使用 Game 来演示模板模式的用法。

Game.java
public abstract class Game {abstract void initialize();abstract void startPlay();abstract void endPlay();//模板public final void play(){//初始化游戏initialize();//开始游戏startPlay();//结束游戏endPlay();}
}
Cricket.java
public class Cricket extends Game {@Overridevoid endPlay() {System.out.println("Cricket Game Finished!");}@Overridevoid initialize() {System.out.println("Cricket Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Cricket Game Started. Enjoy the game!");}
}
Football.java
public class Football extends Game {@Overridevoid endPlay() {System.out.println("Football Game Finished!");}@Overridevoid initialize() {System.out.println("Football Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Football Game Started. Enjoy the game!");}
}
TemplatePatternDemo.java
public class TemplatePatternDemo {public static void main(String[] args) {Game game = new Cricket();game.play();System.out.println();game = new Football();game.play(); }
}
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
我们将创建一个定义接受操作的 ComputerPart 接口。Keyboard、Mouse、Monitor 和 Computer 是实现了 ComputerPart 接口的实体类。我们将定义另一个接口 ComputerPartVisitor,它定义了访问者类的操作。Computer 使用实体访问者来执行相应的动作。
VisitorPatternDemo,我们的演示类使用 Computer、ComputerPartVisitor 类来演示访问者模式的用法。

ComputerPart.java
public interface ComputerPart {public void accept(ComputerPartVisitor computerPartVisitor);
}
Keyboard.java
public class Keyboard implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
Monitor.java
public class Monitor implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
Mouse.java
public class Mouse implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
Computer.java
public class Computer implements ComputerPart {ComputerPart[] parts;public Computer(){parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()}; } @Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {for (int i = 0; i < parts.length; i++) {parts[i].accept(computerPartVisitor);}computerPartVisitor.visit(this);}
}
ComputerPartVisitor.java
public interface ComputerPartVisitor {public void visit(Computer computer);public void visit(Mouse mouse);public void visit(Keyboard keyboard);public void visit(Monitor monitor);
}
ComputerPartDisplayVisitor.java
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {@Overridepublic void visit(Computer computer) {System.out.println("Displaying Computer.");}@Overridepublic void visit(Mouse mouse) {System.out.println("Displaying Mouse.");}@Overridepublic void visit(Keyboard keyboard) {System.out.println("Displaying Keyboard.");}@Overridepublic void visit(Monitor monitor) {System.out.println("Displaying Monitor.");}
}
VisitorPatternDemo.java
public class VisitorPatternDemo {public static void main(String[] args) {ComputerPart computer = new Computer();computer.accept(new ComputerPartDisplayVisitor());}
}
Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.