在你告诉我已经存在类似的问题之前,是的,我知道,我已经读过了.但那里的问题集中在何时,我对其原因感兴趣.
我知道事情是如何运作的.经典的动物,狗,猫的例子总是像魅力一样.
事情是这个代码
int main()
{
Cat c;
Sound theSound;
c.letsDo(&theSound);
}
Run Code Online (Sandbox Code Playgroud)
对我来说似乎很不自然.为什么?
我的意思是,是啊,这样我有我的狗和猫的模型未分化(我第一次用英语BTW这个词),因为真正的implentation是声音类下隐藏,但不只是为了压低你的代码的方式?多态性不足以做这样的事吗?
对我而言,不同之处在于,使用多态性,您必须编辑每个类(但模型保持不变,对吧?)而您只需使用访问者设计模式编辑一个类.
是否可以在 C# 中创建用户可扩展的访问者模式?(最好是 .net 3.5)
我在库中有一组类,我希望使用访问者模式向其中添加功能。问题是库的用户也可以创建自己的类。这意味着您需要创建一个特殊的访问者来接受新的类类型,但我们的 Accept 方法被设置为接收基本类型。如何让派生类在派生访问者中调用正确的方法。
或者是否有另一种方式来做“如果是这种类型,就这样做”?
一些示例代码:
/* In library */
namespace VisitorPattern.System
{
interface IThing
{
void Accept(SystemVisitor visitor);
void ThingMethodA(...);
void ThingMethodB(...);
}
class SystemThingA : IThing
{
public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
...ThingMethods...
}
class SystemThingB : IThing
{
public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
...ThingMethods...
}
class SystemThingC : IThing
{
public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
...ThingMethods...
}
class SystemVisitor
{
public SystemVisitor(object specialSystemServices) { }
public virtual …Run Code Online (Sandbox Code Playgroud) 我在应用程序架构中遇到了障碍.我刚刚开始使用访问者模式在抽象对象上执行特定的算法,这些抽象对象在运行时我不知道.我的问题是我的算法也取决于嵌套抽象类型的类型.
我有一个抽象的DataSource类.从这里我实现了concerete DataSourceReference和DataSourceExplicit类.我还有一个抽象的Report类(反序列化的元数据),我从中实现具体的Report类ReportTypeA和ReportTypeB.创建这些对象时,它们的DataSource可以是任何扩展的DataSource类.
我需要两者,实际的Report类型和DataSource类型,所以我可以相应地执行.我可以使用访问者模式获取协同报告类型,但不知道如何在之后/也为DataSource执行相同操作.
访问报告后我无法访问DataSource,因为我将失去报告的具体类型(因为您必须让它接受基本报告类型:Accept(SomeDataSourceVisitor d,MetaReport m) - 或者为每个可能的报告类型重载,这违背了访客模式的目的.看到我的问题?
有任何想法吗?我不想使用动态,因为它不需要新报表类型的开发人员确保调度程序(访问者)支持新报表.
public abstract class DataSource
{
}
public class DataSourceReference : DataSource
{
// reference thing(s)
}
public class DataSourceExplicit : DataSource
{
// explicit thing(s)
}
public abstract class Report
{
// some shared Report attribute(s)
// ...
public DataSource DataSource { get; set; }
public abstract FinalReport Execute(IReportExecutionDispatcher d);
}
public class ReportA : Report
{
// ReportA specific attribute(s)
// ... …Run Code Online (Sandbox Code Playgroud) architecture abstraction multiple-dispatch double-dispatch visitor-pattern
我有一个图形和一组非常简单的访问者,它们对图形的顶点/边缘进行一些计算,例如获得边缘的总重量和漂亮的图形打印.
我想更进一步,让访问者以DFS方式访问图表.
但是,我认为访问者模式应该与遍历机制分开,并且应该使用其他模式(如迭代器)创建遍历方法.我纠正还是错过了什么?
我找到了这个https://gist.github.com/2945472,但我需要一个不依赖于c ++ 11的实现.我尝试将它转换为仅使用boost,但我遇到了一些麻烦.
这是我想出的:
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/unordered_map.hpp>
struct type_info_hash {
std::size_t operator()(std::type_info const & t) const {
return t.hash_code();
}
};
struct equal_ref {
template <typename T> bool operator()(boost::reference_wrapper<T> a,boost::reference_wrapper<T> b) const {
return a.get() == b.get();
}
};
struct any_visitor {
boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref> fs;
template <typename T> void insert_visitor(boost::function<void(T)> f) {
try {
fs.insert(std::make_pair(boost::ref(typeid(T)), boost::bind(f, boost::any_cast<T>(boost::lambda::_1))));
} catch (boost::bad_any_cast& e) {
std::cout << e.what() << std::endl;
} …Run Code Online (Sandbox Code Playgroud) 使用这两种技术有什么显着的好处吗?如果有变化,我的意思是访客模式:http://en.wikipedia.org/wiki/Visitor_pattern
以下是使用委托实现相同效果的示例(至少我认为它是相同的)
假设有一组嵌套元素:学校包含包含学生的部门
而不是使用访问者模式在每个集合项上执行某些操作,为什么不使用简单的回调(C#中的Action委托)
说这样的话
class Department
{
List Students;
}
class School
{
List Departments;
VisitStudents(Action<Student> actionDelegate)
{
foreach(var dep in this.Departments)
{
foreach(var stu in dep.Students)
{
actionDelegate(stu);
}
}
}
}
School A = new School();
...//populate collections
A.Visit((student)=> { ...Do Something with student... });
Run Code Online (Sandbox Code Playgroud)
*编辑示例,委托接受多个参数
假设我想通过学生和部门,我可以像这样修改动作定义:动作
class School
{
List Departments;
VisitStudents(Action<Student, Department> actionDelegate, Action<Department> d2)
{
foreach(var dep in this.Departments)
{
d2(dep); //This performs a different process.
//Using Visitor pattern would avoid …Run Code Online (Sandbox Code Playgroud) 当我们的对象层次结构纯粹是语义的继承而不是行为的继承时,那么我们不可避免地需要在任何地方编写"instanceof"或"if/else"来进行运行时类型检查.
例如
如果我有一个对象层次结构
Class Function
Class Average extends Function
Class Sum extends Function
Class Max extends Function
Run Code Online (Sandbox Code Playgroud)
如果在这些类中有一个名为calculate()的方法,那么我们没有问题,我们可以利用多态性,这种设计满足LSP.
但是,如果由于某种原因我们不想将此calculate()方法添加到此层次结构中,则这些对象纯粹是对象无状态对象,只表示语义.
然后我们被迫在任何地方编写以下代码:
if (function instanceof Average)
//perform average
else if(function instanceof Sum)
//perform sum
else if(function instanceof Max)
//perform max
Run Code Online (Sandbox Code Playgroud)
上面的代码表明设计不好,因为你在任何地方编写这个代码,这个设计很脆弱,以后很难改变.我想如果数字函数是有限的并且函数的计算在一个地方,这可能是好的取决于复杂性.
到目前为止我所知道的是,要解决上述方法,唯一可行的方法是实现访问者模式,除了使用访问者模式之外,还有其他方法可以解决上述设计吗?
我可以从访问者模式看到的一个问题是访问者模式的accept方法没有返回值,如果accept()方法不能完全满足需求,这有时候不方便.
java design-patterns liskov-substitution-principle instanceof visitor-pattern
请考虑以下之前,我去我的关于特定问题(例如)代码visitor pattern中python:
class Node:
def __init__(self):
self.children = []
def add(self, node):
self.children.append(node)
def check(self):
print("Node")
return True
def accept(self, visitor):
visitor.visit(self)
class NodeA(Node):
def check(self):
print("NodeA")
return True
class NodeB(Node):
def check(self):
print("NodeB")
return True
class NodeA_A(NodeA):
def check(self):
print("NodeA_A")
return True
class NodeA_B(NodeA):
def check(self):
print("NodeA_B")
return True
class NodeA_A_A(NodeA_A):
def check(self):
print("NodeA_A_A")
return False
class NodeRunner:
def visit(self, node):
node.check()
if len(node.children) > 0:
for child in node.children:
child.accept(self)
if __name__ == "__main__": …Run Code Online (Sandbox Code Playgroud) 我正在使用具有多个叶节点类的复合模式,这些类具有专家操作和访问者模式以允许执行这些操作.在这个例子中,accept为了清楚起见,我省略了所有明显的方法.
interface Command {
public int getCost();
}
class SimpleCommand implements Command {
private int cost;
public int getCost() {
return cost;
}
}
class MultiCommand implements Command {
private Command subcommand;
private int repeated;
public int getCost() {
return repeated * subcommand.getCost();
}
public void decrement() {
if (repeated > 0)
repeated--;
}
}
class CommandList implements Command {
private List<Command> commands;
public int getCost() {
return commands.stream().mapToInt(Command::getCost).sum();
}
public void add(Command command) {
commands.add(command);
}
} …Run Code Online (Sandbox Code Playgroud) 我期待在访问者模式的解释在这里,显示下面的代码:
public class ShoppingCart {
public double calculatePostage() {
PostageVisitor visitor = new PostageVisitor();
for(Visitable item: items) {
item.accept(visitor);
}
public class PostageVisitor implements Visitor {
public void visit(Book book) {
public class Book implements Visitable{
public void accept(Visitor vistor) {
visitor.visit(this);
}
Run Code Online (Sandbox Code Playgroud)
从JavaScript开发人员的角度来看,该accept方法似乎是多余的,因为代码可以像这样编写:
for(Visitable item: items) {
// directly call visitor passing an item instead of doing so through `accept` method
visitor.visit(item);
}
Run Code Online (Sandbox Code Playgroud)
我是否正确地认为这不起作用,因为编译器不知道visit访问者的哪个重载方法要执行?
据我所知,编译器了解visit在visitorwith 上执行哪个方法,accept …
visitor-pattern ×10
java ×3
c# ×2
abstraction ×1
architecture ×1
boost ×1
boost-any ×1
c++ ×1
composite ×1
delegates ×1
graph ×1
instanceof ×1
liskov-substitution-principle ×1
python ×1
python-2.7 ×1
visitor ×1