设计模式之组织行为(一)
如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
画图不易,请勿转载。
对象行为组织类
Chain of repository(责任链)
import java.util.*;
abstract class Logger
{
public static int ERR = 3;
public static int NOTICE = 5;
public static int DEBUG = 7;
protected int mask;
// The next element in the chain of responsibility
protected Logger next;
public Logger setNext( Logger l)
{
next = l;
return this;
}
public final void message( String msg, int priority )
{
if ( priority <= mask )
{
writeMessage( msg );
if ( next != null )
{
next.message( msg, priority );
}
}
}
protected abstract void writeMessage( String msg );
}
class StdoutLogger extends Logger
{
public StdoutLogger( int mask ) { this.mask = mask; }
protected void writeMessage( String msg )
{
System.out.println( "Writting to stdout: " + msg );
}
}
class EmailLogger extends Logger
{
public EmailLogger( int mask ) { this.mask = mask; }
protected void writeMessage( String msg )
{
System.out.println( "Sending via email: " + msg );
}
}
class StderrLogger extends Logger
{
public StderrLogger( int mask ) { this.mask = mask; }
protected void writeMessage( String msg )
{
System.out.println( "Sending to stderr: " + msg );
}
}
public class ChainOfResponsibilityExample
{
public static void main( String[] args )
{
// Build the chain of responsibility
Logger l = new StdoutLogger( Logger.DEBUG).setNext(
new EmailLogger( Logger.NOTICE ).setNext(
new StderrLogger( Logger.ERR ) ) );
// Handled by StdoutLogger
l.message( "Entering function y.", Logger.DEBUG );
// Handled by StdoutLogger and EmailLogger
l.message( "Step1 completed.", Logger.NOTICE );
// Handled by all three loggers
l.message( "An error has occurred.", Logger.ERR );
}
}
命令模式(command)
命令模式是比较深刻的设计模式。它抽象了方法«调用过程»,把方法请求和受到影响的类之间的关联解耦。
与这种模式相反的情形就是一个’big function‘,各种情况放在一个函数当中。
import java.util.List;
import java.util.ArrayList;
/* The Command interface */
public interface Command {
void execute();
}
/* The Invoker class */
public class Switch {
private List<Command> history = new ArrayList<Command>();
public Switch() {
}
public void storeAndExecute(Command cmd) {
this.history.add(cmd); // optional
cmd.execute();
}
}
/* The Receiver class */
public class Light {
public Light() {
}
public void turnOn() {
System.out.println("The light is on");
}
public void turnOff() {
System.out.println("The light is off");
}
}
/* The Command for turning on the light - ConcreteCommand #1 */
public class FlipUpCommand implements Command {
private Light theLight;
public FlipUpCommand(Light light) {
this.theLight = light;
}
public void execute(){
theLight.turnOn();
}
}
/* The Command for turning off the light - ConcreteCommand #2 */
public class FlipDownCommand implements Command {
private Light theLight;
public FlipDownCommand(Light light) {
this.theLight = light;
}
public void execute() {
theLight.turnOff();
}
}
/* The test class or client */
public class PressSwitch {
public static void main(String[] args){
Light lamp = new Light();
Command switchUp = new FlipUpCommand(lamp);
Command switchDown = new FlipDownCommand(lamp);
Switch mySwitch = new Switch();
try {
if ("ON".equalsIgnoreCase(args[0])) {
mySwitch.storeAndExecute(switchUp);
}
else if ("OFF".equalsIgnoreCase(args[0])) {
mySwitch.storeAndExecute(switchDown);
}
else {
System.out.println("Argument \"ON\" or \"OFF\" is required.");
}
} catch (Exception e) {
System.out.println("Arguments required.");
}
}
}
解释器(Interpreter)
import java.util.Map;
interface Expression {
public int interpret(final Map<String, Expression> variables);
}
class Number implements Expression {
private int number;
public Number(final int number) { this.number = number; }
public int interpret(final Map<String, Expression> variables) { return number; }
}
class Plus implements Expression {
Expression leftOperand;
Expression rightOperand;
public Plus(final Expression left, final Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret(final Map<String, Expression> variables) {
return leftOperand.interpret(variables) + rightOperand.interpret(variables);
}
}
class Minus implements Expression {
Expression leftOperand;
Expression rightOperand;
public Minus(final Expression left, final Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret(final Map<String, Expression> variables) {
return leftOperand.interpret(variables) - rightOperand.interpret(variables);
}
}
class Variable implements Expression {
private String name;
public Variable(final String name) { this.name = name; }
public int interpret(final Map<String, Expression> variables) {
if (null == variables.get(name)) return 0; // Either return new Number(0).
return variables.get(name).interpret(variables);
}
}
//
import java.util.Map;
import java.util.Stack;
class Evaluator implements Expression {
private Expression syntaxTree;
public Evaluator(final String expression) {
final Stack<Expression> expressionStack = new Stack<Expression>();
for (final String token : expression.split(" ")) {
if (token.equals("+")) {
final Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
expressionStack.push(subExpression);
} else if (token.equals("-")) {
// it's necessary to remove first the right operand from the stack
final Expression right = expressionStack.pop();
// ..and then the left one
final Expression left = expressionStack.pop();
final Expression subExpression = new Minus(left, right);
expressionStack.push(subExpression);
} else
expressionStack.push(new Variable(token));
}
syntaxTree = expressionStack.pop();
}
public int interpret(final Map<String, Expression> context) {
return syntaxTree.interpret(context);
}
}
//
import java.util.Map;
import java.util.HashMap;
public class InterpreterExample {
public static void main(final String[] args) {
final String expression = "w x z - +";
final Evaluator sentence = new Evaluator(expression);
final Map<String, Expression> variables = new HashMap<String, Expression>();
variables.put("w", new Number(5));
variables.put("x", new Number(10));
variables.put("z", new Number(42));
final int result = sentence.interpret(variables);
System.out.println(result);
}
}