设计模式中的第三类是行为型模式,共11种,分别为:

策略、模板方法、观察者、责任链、 迭代子、备忘录、状态、命令、解释器、访问者、调停者。

本篇介绍其最后3种:解释器、访问者、调停者。 

Interpreter
解释器模式
1 解释器模式是类的行为模式,它给定一个语言和此语言文法表达的解释器。客户端可以使用这个解释器来解释语言中的句子。
      解释器模式与编译器的发展历史有关。1972年历史上第一个被广泛使用的计算机语言--c语言诞生了,与其一同诞生的还有第一款c语言
      的编译器,java语言的诞生也得益于c语言,因为它的第一款编译器就是由c开发的。
2 解释器通过一种简单的文法表达式解释一门新的语言。 我们熟知的解释型语言:javascript、 phthon、ruby、php 
    包括网页html、css、以及正则表达式等都是解释器模式的应用案例,就其语言本身来说就可以理解为一个强大的语法"解释器"。 
3 解释器模式中涉及的角色
   (1)抽象表达式角色(Express): 声明一个所有的具体表达式角色都需要实现的抽象接口,这个接口主要有一个interpret()方法,称为解释操作。
   (2)终结表达式(Terminal Expression):这是一个具体角色,它实现了抽象表达式角色所要求的接口,主要是一个interpret()方法。文法中的每一个终结符都有一个具体终结表达式与之对应
   (3)非终结表达式(Nonterminal Expression): 这是一个具体角色。文法中的每一条规则R=R1R2...Rn中的符号都持有一个具体的非终结符的表达式类。对于每一个R1R2...Rn中的符号都持有一个静态类型的Expression实例变量。实现解释操作,即interpret()方法。解释操作已递归方式调用所提到的代表R1R2...Rn中的个符号的实例变量。
   (4)客户端角色(Client) :代表模式的客户单 ,建造一个抽象语法树 ,调用解释操作。
   (5)环境上下文角色(Context): 提供解释器之外的一些全局信息,比如变量的真实量值等。

下面的例子,是运用解释器模式实现java中对布尔表达式的操作运算和求值,它源自GOF原著中的经典例子。

java示例代码:

Expression 解释器接口

package com.jelly.mypattern.interpreter;

/**
 * 解释器   接口
 * @author jelly
 * 解释器的文法表示
 * 
 * Expression   ::=  Expression AND Expression
                | Expression OR  Expression
                | NOT Expression
                | Variable
                | Constant
 *
 */
public interface Expression {
	/**
	 * 解释操作 
	 * @param ctx  上下文环境
	 * @return 
	 */
   public   boolean   interpret(Context ctx);
   public  boolean  equals(Object o);
   public int hashCode();
   public String  toString();
}

Constant 布尔常量类

package com.jelly.mypattern.interpreter;
/**
 *  布尔 常量
 * 例如
 * Constant c=new Constant(true)
 * @author jelly
 *
 */
public class Constant implements  Expression {
  
	private boolean value;
	
	public  Constant(boolean value){
		this.value=value;
		
	}
	/**
	 * 常量 解释运算
	 * 与上下文环境无关,返回其value属性值即可
	 */
	@Override
	public boolean interpret(Context ctx) {
		return  this.value;
	}
	//重写hashCode方法
	@Override
	public int hashCode() {
		return   (this.toString()).hashCode();
	}
	//重写 equals 方法
	@Override
	public boolean equals(Object o) {
		 if(o!=null&& o instanceof Constant){
			 return this.value==((Constant)o).value;
		 }
		 return false;
	}
	//重写toString 方法
	@Override
	public String toString() {
		return new Boolean(value).toString();
	}
    
}

Variable 布尔变量类

package com.jelly.mypattern.interpreter;

/**
 * 布尔   变量类
 * @author jelly
 *
 */
public class Variable implements Expression {

	private String name;

	public Variable(String name) {
		this.name = name;
	}

	@Override
	public boolean interpret(Context ctx) {
		return ctx.lookup(this);
	}

	@Override
	public int hashCode() {
		 return (this.toString()).hashCode();
	}

	@Override
	public boolean equals(Object o) {
		if (o != null && o instanceof Variable) {
			return this.name.equals(((Variable) o).name);
		}
		return false;

	}

	@Override
	public String toString() {
		return name;
	}
	
}

布尔运算上下文类  Context

package com.jelly.mypattern.interpreter;

import java.util.HashMap;
import java.util.Map;

/**
 *布尔运算  上下文类 
 * @author jelly
 *
 */
public class Context {
    private  Map<Variable,Boolean> map=new HashMap<Variable,Boolean>();
	
    public void assign(Variable var,boolean value){
    	map.put(var, new Boolean(value));
    }
	public boolean lookup(Variable var)throws IllegalArgumentException {
		  Boolean value= map.get(var) ;
		if(value==null){
			 throw new IllegalArgumentException();
		}
		return value.booleanValue();
	}
 
}

布尔运算 And 

package com.jelly.mypattern.interpreter;

/**
 * 布尔运算 and
 * @author jelly
 *
 */
public class And  implements  Expression {
    private Expression left;
    private Expression right;
    
	public And(Expression left,Expression right) {
	  this.left=left;
	  this.right=right;
	}

	/**
	 * 解释运算
	 */
	@Override
	public boolean interpret(Context ctx) {
		return left.interpret(ctx)&&right.interpret(ctx);
	}


	@Override
	public int hashCode() {
		return (this.toString()).hashCode();
	}


	@Override
	public boolean equals(Object o) {
		if(o!=null&&o instanceof And){
			return  this.left.equals(((And)o).left) &&
					this.right.equals(((And)o).right);
		}
		return false;
	}

	@Override
	public String toString() {
	   return "("+left.toString()+" AND "+right.toString()+")";
	}
    
	
}

布尔运算 Or

package com.jelly.mypattern.interpreter;

/**
 * 布尔运算  or
 * @author jelly
 *
 */
public class Or  implements Expression{
	private Expression left;
	private Expression right;

	
	public Or(Expression left,Expression right) {
	   this.left=left;
	   this.right=right;
	}

	/**
	 * 解释运算
	 */
	@Override
	public boolean interpret(Context ctx) {
		return left.interpret(ctx)||right.interpret(ctx);
	}

	@Override
	public int hashCode() {
		return (this.toString()).hashCode();
	}

	@Override
	public boolean equals(Object o) {
		if(o!=null&&o instanceof Or){
			return  this.left.equals(((Or)o).left) &&
					this.right.equals(((Or)o).right);
		}
		return false;
	}

	@Override
	public String toString() {
		return "("+left.toString()+" OR "+right.toString()+")";
	}
	
	

}

布尔运算 Not

package com.jelly.mypattern.interpreter;

/**
 * 布尔运算 not
 * @author jelly
 *
 */
public class Not implements Expression{
	private Expression exp;

	public Not(Expression exp) {
		  this.exp=exp;
	}

	@Override
	public boolean interpret(Context ctx) {
	   return   !exp.interpret(ctx);
	}

	@Override
	public int hashCode() {
		return (this.toString()).hashCode();
	}

	@Override
	public boolean equals(Object o) {
		if(o!=null&&o instanceof Not){
			return this.exp.equals(((Not)o).exp);
		}
		
		return false;
	}

	@Override
	public String toString() {
		return  "(NOT "+exp.toString()+")";
	}

	
}

测试代码

package com.jelly.mypattern.interpreter;

/**
 * 解释器模式    客户端测试代码
 * @author jelly
 *
 */
public class InterpreterTest {

	public static void main(String[] args) {
		Context ctx=new Context();
		//x y 表示2个布尔变量对象    c表示一个布尔常量对象
		Variable x=new Variable("x");
		Variable y=new Variable("y");
		Constant c=new Constant(true);
		//ctx 指定变量x的值为false 变量y为true,并存放到上下文对象map中
		ctx.assign(x, false);
		ctx.assign(y, true);
		
		Expression  exp=new Or(new And(c,x),new And(y,new Not(x)));
		System.out.println("执行布尔表达式运算: "+exp.toString());
		System.out.println("运算结果为: "+exp.interpret(ctx));
	}
	 
}

控制台输出:

执行布尔表达式运算: ((true AND x) OR (y AND (NOT x)))
 运算结果为: true

Visitor
访问者模式
1 访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可  保持不变。适用于对数据结构复杂又相对稳定的对象访问。
2 访问者模式中涉及的角色
  抽象访问者角色(Visitor):声明了一个或多个访问操作,形成所有的具体元素角色必须实现的接口
  具体访问者(ConcreteVisitor):实现抽象访问者角色所声明的接口。
  抽象节点(Node):声明一个接受操作,接受一个访问者对象作为一个参量。
  具体节点(ConcreteNode):实现抽象元素节点定义的接受操作。

3 单分派与多分派。
   由于java中类、接口之间存在继承和实现的关系,多态由此而产生。java中对象的多态性体现在,在程序的运行期,java会动态判断对象的真实类型,从而准确地   调用对象真实类型的方法。(相对地,我们编译期的对象类型为静态类型)。然而java中的方法接收的参数(称为方法参量,方法接收者与方法参量统称为方法的宗量)   在方法执行期间却不能动态判断出参量的真实类型。也就是说java是"单分派"的语言(至少目前如此),  然而我们可以通过设计模式达到"双分派"的目的。这就是访  问者模式,它通过两次次"单分派"达到"双重分派"的目标,但是从本质上来说"双重分派"仍不等同于"双分派"。

访问者模式适用于访问/遍历数据结构(聚集)比较复杂,又相对稳定的对象(通常是聚集对象)

下面是java示例代码:

ObjectStructure 聚集类/模拟一个复杂的数据结构

package com.jelly.mypattern.visitor;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 数据结构对象,模拟 一个复杂的数据结构聚集对象
 * @author jelly
 *
 */
public class ObjectStructure {
   private List<Node> nodeList;

    public ObjectStructure() {
    	nodeList=  new ArrayList<Node>();
   }
   
   
    public void add(Node node){
    	nodeList.add(node);
    }
    
    /**
     * 运行visitor 访问者访问 自身
     * 暴露给visitor 的访问方法
     * @param visitor
     */
    public void action(Visitor visitor){
    	Iterator<Node> it=   nodeList.iterator();
    	while( it.hasNext()){
    		Node node=  it.next();
    		node.accept(visitor);
    	}
    }
}

Node 抽象节点

package com.jelly.mypattern.visitor;

/**
 * 抽象节点
 * @author jelly
 *
 */
public abstract class Node {
  
	public abstract void accept(Visitor visitor);
}

NodeA  具体节点A

package com.jelly.mypattern.visitor;

/**
 * 具体节点 a
 * @author jelly
 *
 */
public class NodeA  extends Node{
	
	//访问nodeA 节点
	public String operationA(){
	   return "nodeA 的operationA方法执行...";
	}
	//访问nodeB 节点
	public String operationA2(){
		return "nodeA 的operationA2方法执行...";
	}
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}
}

NodeB 具体节点B

package com.jelly.mypattern.visitor;

/**
 * 具体节点 b
 * @author jelly
 *
 */
public class NodeB  extends Node{
	    public String operationB(){
		   return "nodeB 的operationB方法执行...";
		}
	    public String operationB2(){
			   return "nodeB 的operationB2方法执行...";
		}
		@Override
		public void accept(Visitor visitor) {
			visitor.visit(this);
		}
}

抽象访问者 Visitor

package com.jelly.mypattern.visitor;

/**
 * 抽象访问者角色
 * @author jelly
 *
 */
public interface Visitor {
   public void visit(NodeA node);
   public void visit(NodeB node);
   
}

具体访问者A  VisitorA

package com.jelly.mypattern.visitor;

/**
 * 具体访问者A
 * @author jelly
 *
 */
public class VisitorA  implements Visitor{

	@Override
	public void visit(NodeA node) {
		 System.out.println(node.operationA());
	}

	@Override
	public void visit(NodeB node) {
		System.out.println(node.operationB());
	}

}

具体访问者B VisitorB

package com.jelly.mypattern.visitor;

/**
 * 具体访问者B
 * @author jelly
 *
 */
public class VisitorB implements  Visitor{

	//访问nodeA 节点
	@Override
	public void visit(NodeA node) {
	 
		System.out.println(node.operationA());
		System.out.println(node.operationA2());
	}
	//访问nodeB 节点
	@Override
	public void visit(NodeB node) {
		 System.out.println(node.operationB());
		 System.out.println(node.operationB2());
	}

}

测试代码:

package com.jelly.mypattern.visitor;

/**
 * 访问者模式 测试代码
 * @author jelly
 *
 */
public class VisitorTest {
  public static void main(String[] args) {
	   ObjectStructure  objstruct=new ObjectStructure();
	   Node node1=new NodeA();
	   Node node2=new NodeB();
	   Node node3=new NodeA();
	   Node node4=new NodeB();
	   objstruct.add(node1);
	   objstruct.add(node2);
	   objstruct.add(node3);
	   objstruct.add(node4);
	   
	   Visitor visitor1=new VisitorA();
	   objstruct.action(visitor1);
	   System.out.println("---------");
	   Visitor visitor2=new VisitorB();
	   objstruct.action(visitor2);
  }
}

控制台输出:

nodeA 的operationA方法执行...
 nodeB 的operationB方法执行...
 nodeA 的operationA方法执行...
 nodeB 的operationB方法执行...
 ---------
 nodeA 的operationA方法执行...
 nodeA 的operationA2方法执行...
 nodeB 的operationB方法执行...
 nodeB 的operationB2方法执行...
 nodeA 的operationA方法执行...
 nodeA 的operationA2方法执行...
 nodeB 的operationB方法执行...
 nodeB 的operationB2方法执行...

Mediator
调停者模式 ,也叫中介模式
调停者模式是对象的行为模式,它包装了一系列对象相互作用的方式,使得这些对象不必显示地相互引用。从而可以使它们可以松散地耦合,保证这些相互作用可以彼此独立地变化。

如下图所示,这个示意图中有大量的对象,这些对象既会影响到别的对象,又会被别的对象所影响,因此常常叫做同事对象(Colleague)。

 这些同事对象通过彼此的相互作用形成系统的行为。从图中可以看出,几乎每一个对象都需要与其他对象发生相互的作用,而这种相互作用表现为一个对象与另一个对象的直接耦合。这是一个过度耦合的系统。 

 

java 系统多语言设计 java语言设计模式_设计模式

 

通过引入调停者(Mediator),可以将系统的网状结构变为以中介为中心的星形结构。

如图所示,在这个星形状结构中,同事对象不再通过直接的联系与另一个对象发生相互作用;相反地,它通过调停者对象与另外一个对象发生作用。

调停者对象的存在保证了对象结构上的稳定,也就是说,系统的结构不会因为新对象的引入造成大量的修改工作。 

 

 

java 系统多语言设计 java语言设计模式_java_02

 调停者模式中的角色:
   抽象调停者: 定义出同事对象到调停者模式对象的接口,其主要方法是一个(或多个)事件方法。在有些情况下,这个抽象对象可以省略。一般而言,这个角色由一个java抽象类或java对象实现。
   具体调停者:从抽象调停者继承而来,实现类的抽象超类的事件方法。具体调停者知晓所有的具体同事类,它从一个具体同事类对象接收消息、向具体同事对象发出命令。
   抽象同事角色: 定义出调停者到同事对象的结果。同事对象只知道调停者而不知道其余同事对象。
   具体同事角色:具体同事类都很清楚自己在小范围内的行为,而不知道它在大范围内的目的。
   
 java 示例代码

Mediator 抽象调停者 

package com.jelly.mypattern.mediator;

/**
 * 调停者 
 * @author jelly
 *
 */
public  abstract class Mediator {

	public  abstract void colleagueChanged(Colleague c);
    
}

ConcreteMediator 具体调停者

package com.jelly.mypattern.mediator;

/**
 * 具体调停者  类
 * @author jelly
 *
 */
public class ConcreteMediator extends Mediator {
	private ColleagueA colleagueA;
	private ColleagueB colleagueB;

	@Override
	public void colleagueChanged(Colleague c) {
	    System.out.println(c+" 对象发生变化");
	    colleagueA.action();
	    colleagueB.action();
	}
    public void createConcreteMediator(){
    	colleagueA=new ColleagueA(this);
    	colleagueB=new ColleagueB(this);
    }
	 
	public ColleagueA getColleagueA() {
		return colleagueA;
	}

	public ColleagueB getColleagueB() {
		return colleagueB;
	}

	 
}

抽象同事类 Colleague 

package com.jelly.mypattern.mediator;

/**
 * 同事 抽象类
 * @author jelly
 *
 */
public abstract class Colleague {
    private Mediator mediator;
	public Colleague( Mediator mediator) {
		this.mediator=mediator;
	}
	public Mediator getMediator() {
		return mediator;
	}
   //抽象行动方法
   public  abstract void action();
   
   public void change(){
	   mediator.colleagueChanged(this);
   }
}

同事类A

package com.jelly.mypattern.mediator;

/**
 * 同事类A
 * @author jelly
 *
 */
public class ColleagueA  extends Colleague{

	public ColleagueA(Mediator mediator) {
		super(mediator);
	}
	/**
	 * colleagueA 中的具体行动方法
	 */
	@Override
	public void action() {
		System.out.println("colleagueA do something ...");
	}
 
}

同事类B

package com.jelly.mypattern.mediator;


/**
 * 同事类B
 * @author jelly
 *
 */
public class ColleagueB  extends Colleague{
	public ColleagueB(Mediator mediator) {
		super(mediator);
	}

	/**
	 * colleagueB 中的具体行动方法
	 */
	@Override
	public void action() {
		System.out.println("colleagueB do something ...");
	}
 
}

测试代码:

package com.jelly.mypattern.mediator;

/**
 * 测试代码
 * @author jelly
 *
 */
public class MediatorTest {
	 public static void main(String[] args) {
		    ConcreteMediator mediator=new ConcreteMediator();
		    mediator.createConcreteMediator();
		   
		    Colleague  c=new ColleagueA(mediator);
		    mediator.colleagueChanged(c);
	     
	 }
}

控制台输出:

com.jelly.mypattern.mediator.ColleagueA@4be8b8 对象发生变化
 colleagueA do something ...
 colleagueB do something ...

至此,笔者已将GOF中的23种设计模式全部介绍完毕,然而现实中模式并非仅仅只有这些。我们天天说的MVC模式,它是一种模式,又因为它太大,贯穿于整个项目之中,所以又是一种面向对象的架构。时代变迁,模式也在不断地发展,现今各种各样的模式层出不穷,早已超出了GOF原著中的23种,它们中的绝大多数越来越多地被开发者所采纳。

然而模式万万不可被滥用,不要为用模式而使用模式。恰当的模式运用能够成就一个优秀的项目,不当的模式运用也能毁掉一个项目。在我们的开发过程中,必须要结合需求场景,分清场合地使用模式