1 行为模式
行为模式主要涉及到算法和对象间职责的分配。行为类模式使用继承机制在类间分配行为。比如模板方法模式,解释器模式。
行为对象模式使用对象复用而不是继承。
1.1 模板方法模式
1.1.1 意图
Template Method: 定义一个操作中算法的骨架,而将一些步骤延迟到子类。
1.1.2实用性
模板方法应用于下列情况:
• 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
• 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
• 控制子类扩展。
1.1.3结构
1.1.4优缺点
封装不变部分,扩展可变部分。提取公共部分代码,便于维护。行为由父类控制,子类实现。
1.1.5参与者
• A b s t r a c t C l a s s
— 定义抽象的原语操作( primitive operation),具体的子类将重定义它们以实现一个算法
— 实现一个模板方法,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义
在A b s t r a c t C l a s s或其他对象中的操作。
• C o n c r e t e C l a s s
— 实现原语操作以完成算法中与特定子类相关的步骤。
1. AbstractClass
public abstract class AbstractClass {
//
基本方法
protected abstract void doSomething();
//
基本方法
protected abstract void doAnything();
//
模版方法
public void templateMethod(){
/*
*
调用基本方法,完成相关的逻辑
*/
this.doAnything();
this.doSomething();
}
}
2.
ConcreteClass1
public class ConcreteClass1 extends AbstractClass {
//
实现基本方法
protected void doAnything() {
//
业务逻辑处理
}
protected void doSomething() {
//
业务逻辑处理
}
}
1.2 解释器模式
1.2.1 意图
Interpreter: 给定一门语言,定义它文法的一种表示,并定义一个解释器,这个解释器使用该表示可以解释语言中的句子。
1.2.2实用性
当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
• 该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。
• 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。
1.2.3结构
1.2.4优缺点
解释器是一个简单的语法分析工具,最显著的优点就是扩展性,修改语法规则只要修改相应的非终结表达式就可以了,若扩展语法,则只要添加非终结符类就可以了。
解释模式的缺点:解释器模式会引起类膨胀,每个语法都要产生一个非终结表达式;采用递归调用方法;效率问题,由于使用了大量的循环和递归,效率是一个问题。
1.2.5参与者
• A b s t r a c t E x p r e s s i o n (抽象表达式)
— 声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
• Te r m i n a l E x p r e s s i o n (终结符表达式)
— 实现与文法中的终结符相关联的解释操作。
— 一个句子中的每个终结符需要该类的一个实例。
• N o n t e r m i n a l E x p r e s s i o n (非终结符表达式)
— 对文法中的每一条规则R ::= R1R2. . . Rn都需要一个N o n t e r m i n a l E x p r e s s i o n类。
— 为从R1到Rn的每个符号都维护一个A b s t r a c t E x p r e s s i o n类型的实例变量。
— 为文法中的非终结符实现解释( I n t e r p r e t )操作。解释( I n t e r p r e t )一般要递归地调用表示
R1到Rn的那些对象的解释操作。
• C o n t e x t(上下文)
— 包含解释器之外的一些全局信息。
• C l i e n t(客户)
— 构建(或被给定) 表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由N o n t e r m i n a l E x p r e s s i o n和Te r m i n a l E x p r e s s i o n的实例装配而成。
— 调用解释操作。
1.
Expression
public abstract class Expression {
//
每个表达式必须有一个解析任务
public abstract Object interpreter(Context ctx);
}
2.
NonterminalExpression
public class NonterminalExpression extends Expression {
//
每个非终结符表达式都会对其他表达式产生依赖
public NonterminalExpression(Expression... expression){
}
public Object interpreter(Context ctx) {
//
进行文法处理
return null;
}
}
3.
TerminalExpression
public class TerminalExpression extends Expression {
//
通常终结符表达式只有一个,但是有多个对象
public Object interpreter(Context ctx) {
return null;
}
}
4.
Context
public class Context {
}
5.
Client
public class Client {
public static void main(String[] args) {
Context ctx = new Context();
//
通常定一个语法容器,容纳一个具体的表达式,通常为ListArray,LinkedList,Stack等类型
Stack<Expression> stack = null;
/*
for(;;){
//
进行语法判断,并产生递归调用
}
*/
//
产生一个完整的语法树,由各各个具体的语法分析进行解析
Expression exp = stack.pop();
//
具体元素进入场景
exp.interpreter(ctx);
}
}
1.3 责任链模式
1.3.1 意图
Chain Of Resopnsibility: 使得多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这些对象形成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
1.3.2实用性
在以下条件下使用Responsibility链:
• 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
• 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
• 可处理一个请求的对象集合应被动态指定。
1.3.3结构
1.3.4优缺点
责任链模式将请求与处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求者,两者解耦,提高系统的灵活性。
缺点则是:一性能问题,链比较长的时候,性能是个大问题;二调试不方便,由于使用了类似递归的方法。
1.3.5参与者
• H a n d l e r
— 定义一个处理请求的接口。
— (可选) 实现后继链。
• C o n c r e t e H a n d l e r
— 处理它所负责的请求。
— 可访问它的后继者。
— 如果可处理该请求,就处理之;否则将该请求转发给它的后继者。
• C l i e n t
— 向链上的具体处理者( C o n c r e t e H a n d l e r )对象提交请求。
1.
Handler
public abstract class Handler {
private Handler nextHandler;
//
每个处理者都必须对请求做出处理
public final Response handlerMessage(Request request){
Response response = null;
//
判断是否是自己的处理级别
if(this.getHandlerLevel().equals(request.getRequestLevel())){
response = this.echo(request);
}else{ //
不属于自己的处理级别
//
判断是否有下一个处理者
if(this.nextHandler != null){
response = this.nextHandler.handlerMessage(request);
}else{
//
没有适当的处理者,业务自行处理
}
}
return response;
}
//
设置下一个处理者是谁
public void setNext(Handler _handler){
this.nextHandler = _handler;
}
//
每个处理者都有一个处理级别
protected abstract Level getHandlerLevel();
//
每个处理者都必须实现处理任务
protected abstract Response echo(Request request);
}
2.
ConcreteHandler1
public class ConcreteHandler1 extends Handler {
//
定义自己的处理逻辑
protected Response echo(Request request) {
//
完成处理逻辑
return null;
}
//
设置自己的处理级别
protected Level getHandlerLevel() {
//
设置自己的处理级别
return null;
}
}
3.
Level
public class Level {
//
定义一个请求和处理等级
}
4.
Request
public class Request {
//
请求的等级
public Level getRequestLevel(){
return null;
}
}