最近看了刘老师写的设计模式,解释器模式自定义语言的实现——解释器模式(六)_刘伟技术博客-CSDN博客,来做一下老师留的练习题。
练习
Sunny软件公司欲为数据库备份和同步开发一套简单的数据库同步指令,通过指令可以对数据库中的数据和结构进行备份,例如,输入指令“COPY VIEW FROM srcDB TO desDB”表示将数据库srcDB中的所有视图(View)对象都拷贝至数据库desDB;输入指令“MOVE TABLE Student FROM srcDB TO desDB”表示将数据库srcDB中的Student表移动至数据库desDB。试使用解释器模式来设计并实现该数据库同步指令。
首先分析一下指令的内容 :COPY VIEW FROM srcDB TO desDB 。其中一条指令有
COPY 动作,来描述复制还是移动。
VIEW 处理的目标对象可以是表,视图,函数等。后面没有特殊字段表示全部,有的话表示对象名称。
FROM srcDB 原始库。
TO desDB 目标库。
这样得到一条“指令”是由4部分组成,“动作”,“目标对象”,“原始库”,“目标库”组成。由此我们构建对应的class.
先定义指令节点抽象接口。
package com.pattern.explaindb.abs; import com.pattern.explaindb.Context; public interface AbstractDbNode { void interpret(Context context); String execute(); }
定义上下文对象Context
package com.pattern.explaindb; import java.util.StringTokenizer; public class Context { public StringTokenizer tokenizer; public String currentToken; public Context(String test) { tokenizer = new StringTokenizer(test); nextToken(); } public String nextToken() { if(tokenizer.hasMoreTokens()){ currentToken = tokenizer.nextToken(); }else{ currentToken = null; } return currentToken; } public String currentToken() { return currentToken; } public void skipToken(String token){ if(!token.equals(currentToken)){ System.out.println("错误:" + currentToken + "解释错误!"); } nextToken(); } }
分别定义“动作”,
package com.pattern.explaindb; import com.pattern.explaindb.abs.AbstractDbNode; public class OperateNode implements AbstractDbNode { private String operate; //动作 private String opname; //动作名称 @Override public void interpret(Context context) { operate = context.currentToken(); context.skipToken(operate); if("COPY".equals(operate)){ opname = "复制"; }else if("MOVE".equals(operate)){ opname = "移动"; }else{ opname = "无法识别命令"; } } @Override public String execute() { return opname; } }
定义:“目标对象”,
package com.pattern.explaindb; import com.pattern.explaindb.abs.AbstractDbNode; public class OptionalNode implements AbstractDbNode { private String option; // *** 作对象 private String optionname; // *** 作对象名称 private String target; @Override public void interpret(Context context) { option = context.currentToken(); context.skipToken(option); //option的类型可以有各种,表,视图,函数,序列,触发器等等。 if("VIEW".equals(option)){ optionname = "视图"; }else if("TABLE".equals(option)){ optionname = "表"; }else if("FUNCTION".equals(option)){ optionname = "函数"; }else{ optionname = "无法识别命令"; } target = context.currentToken(); if("FROM".equals(target)){ target = ""; }else{ context.skipToken(target); } } @Override public String execute() { return optionname + target; } }
定义:“库”对象
package com.pattern.explaindb; import com.pattern.explaindb.abs.AbstractDbNode; public class DbNode implements AbstractDbNode { private String dbName; @Override public void interpret(Context context) { String op = context.currentToken(); if("FROM".equals(op) || "TO".equals(op)){ context.skipToken(op); } dbName = context.currentToken(); context.skipToken(dbName); } @Override public String execute() { return dbName; } }
然后定义 “指令对象”
package com.pattern.explaindb; import com.pattern.explaindb.abs.AbstractDbNode; public class OptionNode implements AbstractDbNode { private AbstractDbNode operate, optional, fromDb,targetDb; //动作, *** 作对象,原始库,目标库 @Override public void interpret(Context context) { operate = new OperateNode(); operate.interpret(context); optional = new OptionalNode(); optional.interpret(context); fromDb = new DbNode(); fromDb.interpret(context); targetDb = new DbNode(); targetDb.interpret(context); } @Override public String execute() { return "将数据库" + fromDb.execute() + "中的" + optional.execute() + operate.execute() + "至数据库" + targetDb.execute(); } }
最后定义一个指令“解释器”:
package com.pattern.explaindb; import com.pattern.explaindb.abs.AbstractDbNode; import java.util.ArrayList; import java.util.List; public class expressionNode implements AbstractDbNode { private List nodes = new ArrayList<>(); @Override public void interpret(Context context) { while (true){ if(context.currentToken() == null){ break; }else{ AbstractDbNode node = new OptionNode(); node.interpret(context); nodes.add(node); } } } @Override public String execute() { String result = ""; for (AbstractDbNode node : nodes) { result += node.execute(); } return result; } }
最后写一个main方法执行一下。
package com.pattern.explaindb; import com.pattern.explaindb.abs.AbstractDbNode; public class Client { public static void main(String[] args) { //String str = "COPY VIEW FROM srcDB TO desDB"; //String str = "MOVE TABLE Student FROM srcDB TO desDB"; String str = "MOVE FUNCTION Student FROM srcDB TO desDB"; Context context = new Context(str); AbstractDbNode node = new expressionNode(); node.interpret(context); System.out.println(node.execute()); } }
执行结果为:
将数据库srcDB中的函数Student移动至数据库desDB
这样就做完了,有改进的地方希望能帮忙指正。感谢!!!!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)