我正在上课,我们刚刚了解了这些设计模式.但是我看不出它们之间有什么区别.它们听起来像是一样的,在抽象的类上创建具体的类.有人可以帮我解决这个疑问吗?谢谢 (:
design-patterns strategy-pattern visitor template-method-pattern
我正在为我们系统的一部分编写数据层,该数据层记录有关每天运行的自动作业的信息 - 作业名称,运行时间,结果,等等.
我正在使用Entity Framework与数据库交谈,但我试图将这些细节隐藏在更高级别的模块之外,我不希望实体对象本身被暴露.
但是,我想使我的界面在用于查找作业信息的标准中非常灵活.例如,用户界面应允许用户执行复杂的查询,例如"给我所有名为'hello'的作业,该作业在上午10:00到11:00之间运行失败." 显然,这看起来像是动态构建Expression树的工作.
所以我希望我的数据层(存储库)能够接受类型Expression<Func<string, DateTime, ResultCode, long, bool>>(lambda表达式)的LINQ表达式,然后在后台将该lambda转换为我的实体框架ObjectContext可以用作Where()子句中的过滤器的表达式.
简而言之,我正在尝试将类型的lambda表达式转换Expression<Func<string, DateTime, ResultCode, long, bool>>为Expression<Func<svc_JobAudit, bool>>,其中svc_JobAuditEntity Framework数据对象对应于存储作业信息的表.(第一个委托中的四个参数分别对应于作业名称,运行时间,结果以及分别在MS中花费的时间)
我在使用该ExpressionVisitor课程时取得了很好的进展,直到我碰到了一堵砖墙并收到了一条InvalidOperationException错误消息:
从"VisitLambda"调用时,重写"System.Linq.Expressions.ParameterExpression"类型的节点必须返回相同类型的非null值.或者,覆盖"VisitLambda"并将其更改为不访问此类型的子项.
我完全不知所措.为什么它不允许我将引用参数的表达式节点转换为引用属性的节点?还有另一种方法可以解决这个问题吗?
以下是一些示例代码:
namespace ExpressionTest
{
class Program
{
static void Main(string[] args)
{
Expression<Func<string, DateTime, ResultCode, long, bool>> expression = (myString, myDateTime, myResultCode, myTimeSpan) => myResultCode == ResultCode.Failed && myString == "hello";
var result = ConvertExpression(expression);
}
private static Expression<Func<svc_JobAudit, bool>> …Run Code Online (Sandbox Code Playgroud) 我写了一个很好的简单的小域模型,其对象图如下所示:
-- Customer
-- Name : Name
-- Account : CustomerAccount
-- HomeAddress : PostalAddress
-- InvoiceAddress : PostalAddress
-- HomePhoneNumber : TelephoneNumber
-- WorkPhoneNumber : TelephoneNumber
-- MobilePhoneNumber : TelephoneNumber
-- EmailAddress : EmailAddress
Run Code Online (Sandbox Code Playgroud)
这个结构与我必须使用的遗留数据库完全不一致,所以我定义了一个平面DTO,其中包含客户图中每个元素的数据 - 我在数据库中有视图和存储过程,这些允许我在这两个方向上使用这种扁平结构与数据进行交互,这一切都很好,花花公子:)
将域模型展平为DTO以进行插入/更新是直截了当的,但我遇到的问题是使用DTO并从中创建域模型...我的第一个想法是实现访问每个元素的访问者客户图,并根据需要从DTO注入值,有点像这样:
class CustomerVisitor
{
public CustomerVisitor(CustomerDTO data) {...}
private CustomerDTO Data;
public void VisitCustomer(Customer customer)
{
customer.SomeValue = this.Data.SomeValue;
}
public void VisitName(Name name)
{
name.Title = this.Data.NameTitle;
name.FirstName = this.Data.NameFirstName;
name.LastName = this.Data.NameLastName;
}
// ... and so on …Run Code Online (Sandbox Code Playgroud) 我一直在寻找在Objective-C中实现Visitor设计模式的最佳方法.由于该语言不支持方法重载,因此在Java中可能发现的"传统"实现似乎是不可能的.
在我当前的实现中,我有一个Visitor协议,一个Visitor类,以及该Visitor类的几个子类,以及要访问的各种对象.一旦访问对象接受访问者,他们就会调用访问者的访问方法,将自己作为参数传递.visit方法接受一个id,然后键入它并调用它
[self performTasksOnObjectClass: (ObjectClass *)object];
Run Code Online (Sandbox Code Playgroud)
作为if/elseif/else块的一部分.这些调用由相关的Visitor子类拾取,访问者执行对象所需的任何任务.
有没有比这更好的实现访客模式的方法?我不喜欢在if/elseif/else块中使用'isKindOfClass'或'isMemberOfClass'调用.它看起来很笨重而且不够优雅.另外,以这种方式实现Visitor方法还值得吗?访问过的对象仍然可以不知道访问者,但还有其他方法可以实现这一点.
已经有人提出,委托或类集群可能是访客模式的更合适的替代方案.我有兴趣看看你们都在想什么!
编辑:我实际上在子类中调用了不同的命名方法,我已经更清楚了.
这是C++中访问者模式的简化实现.我有可能在Python中实现这样的东西吗?
我需要它,因为我会将对象从C++代码传递给Python中的函数.我的想法是在Python中实现一个访问者来找出Object的类型.
我的C++代码:
#include <iostream>
#include <string>
class t_element_base
{
public:
virtual void accept( class t_visitor &v ) = 0;
};
class t_element_deriv_one: public t_element_base
{
public:
void accept( t_visitor &v );
std::string t_element_deriv_one_text()
{
return "t_element_deriv_one";
}
};
class t_element_deriv_two: public t_element_base
{
public:
void accept( t_visitor &v );
std::string t_element_deriv_two_text()
{
return "t_element_deriv_one";
}
};
class t_visitor
{
public:
void visit( t_element_deriv_one& e ){ std::cout << e.t_element_deriv_one_text() << std::endl; }
void visit( t_element_deriv_two& e ){ std::cout << e.t_element_deriv_two_text() …Run Code Online (Sandbox Code Playgroud) 我试图将以下Haskell代码转换为C++:
data List t = Nil | Cons t (List t)
Run Code Online (Sandbox Code Playgroud)
将代数数据类型直接转换为无状态访问者模式会产生以下Java代码
interface List<T> {
<R> R accept(ListVisitor<T,R> v);
}
interface ListVisitor<T,R> {
R visitNil();
R visitCons(T head, List<T> tail);
}
class Nil<T> implements List<T> {
@Override
public <R> R accept(ListVisitor<T,R> v) {
return v.visitNil();
}
}
class Cons<T> implements List<T> {
public final T head;
public final List<T> tail;
public Cons(T head, List<T> tail) {
this.head = head;
this.tail = tail;
}
@Override
public <R> R accept(ListVisitor<T,R> v) { …Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,我在一系列元素上执行操作,操作的确切性质取决于所操作元素的类型.由于封装的原因,元素不适合实现操作; 这意味着它不能是元素类型的虚方法,所以'标准'多态不起作用.我提出了一个与之相关的问题,并被告知这被称为访客模式.
我以前总是使用if/elseif基于对象类型的调度程序方法实现它,然后调用适当的实现.然而,最近,我注意到同样的事情可能是使用dynamic关键字完成,如下所示:
private void ReconcileTips()
{
foreach (var step in _definition.Steps)
{
ReconcileTips((dynamic)step);
}
}
private void ReconcileTips(IBulkDispenseDefinition bulkDispense)
{
bulkDispense.TipType = ReconcileTip(bulkDispense.TipType);
}
private void ReconcileTips(ImportScreenDefinition importScreen)
{
foreach (var usage in importScreen.ReagentUsages)
usage.TipType = ReconcileTip(usage.TipType);
}
private void ReconcileTips(BuildScreenDefinition buildScreen)
{
foreach (var function in buildScreen.Functions)
function.TipType = ReconcileTip(function.TipType);
}
Run Code Online (Sandbox Code Playgroud)
类似的模式可以用于与类结构并行的其他操作,比如为每个元素创建视图模型_definition.Steps.我们的想法是,编译器基本上将其转换为if/elseif我之前编写的相同逻辑,从而节省了我的努力.那么,有几个问题:
动态调度是否有任何问题我没有考虑过?我相信这相当于执行一系列if (x is TypeA) Do((TypeA)x) else...,但我可能是错的.
这比较长的if/elseif方法更清洁,更容易理解吗?
我是antlr的初学者.我试图在我的代码中使用访问者并遵循网络上的说明.但是,我发现访问者没有进入我创建的方法.愿谁有人告诉我我做错了什么?
这是我的访客:
import java.util.LinkedList;
import org.antlr.v4.runtime.misc.NotNull;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Sherwood
*/
public class ExtractMicroBaseVisitor extends MicroBaseVisitor<Integer> {
//LinkedList<IR> ll = new LinkedList<IR>();
//MicroParser parser;
//System.out.println("11");
@Override
public Integer visitPgm_body(@NotNull MicroParser.Pgm_bodyContext ctx){
System.out.println(ctx.getText());
return 467;
}
@Override
public Integer visitProgram(@NotNull MicroParser.ProgramContext ctx){
System.out.println("11");
return 456;
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,当输入方法"visitProgram"时,stdout应打印11.但输出屏幕没有给我任何东西(null类型).
这是我的主要代码:
import java.io.IOException;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
/**
*
* @author Sherwood
*/ …Run Code Online (Sandbox Code Playgroud) 我很有诱惑力使用未经检查的异常作为Java程序中的短路控制流构造.我希望有人能以更好,更清洁的方式告诉我这个问题.
我的想法是,我希望减少访问者对子树的递归探索,而不必在每个方法调用中检查"停止"标志.具体来说,我正在使用抽象语法树上的访问者构建控制流图.returnAST中的语句应该停止对子树的探索,并将访问者发送回最近的封闭if/then或循环块.
的Visitor超类(从XTC库)定义
Object dispatch(Node n)
Run Code Online (Sandbox Code Playgroud)
通过表单的反射方法回调
Object visitNodeSubtype(Node n)
Run Code Online (Sandbox Code Playgroud)
dispatch 没有声明抛出任何异常,所以我声明了一个扩展的私有类 RuntimeException
private static class ReturnException extends RuntimeException {
}
Run Code Online (Sandbox Code Playgroud)
现在,return语句的visitor方法看起来像
Object visitReturnStatement(Node n) {
// handle return value assignment...
// add flow edge to exit node...
throw new ReturnException();
}
Run Code Online (Sandbox Code Playgroud)
并且每个复合语句都需要处理 ReturnException
Object visitIfElseStatement(Node n) {
Node test = n.getChild(0);
Node ifPart = n.getChild(1);
Node elsePart = n.getChild(2);
// add flow edges to if/else...
try{ dispatch(ifPart); } catch( ReturnException e ) { …Run Code Online (Sandbox Code Playgroud)