[英]what is the difference between visitor and strategy pattern?
I have learned both the patterns but did not understand the differences between these two patterns.我已经学习了这两种模式,但不了解这两种模式之间的区别。
I do not know scenarios, when and where to use these patterns.我不知道场景,何时何地使用这些模式。
Can any one explain the differences and use cases?任何人都可以解释差异和用例吗?
The main difference is that the Strategy Pattern encapsulates a single group of related behaviors, while the Visitor Pattern encapsulates multiple such groups.主要区别在于策略模式封装了一组相关的行为,而访问者模式封装了多个这样的组。
Visitor pattern intent:访客模式意图:
Represent an operation to be performed on the elements of an object structure.表示要对对象结构的元素执行的操作。 Visitor lets you define a new operation without changing the classes of the elements on which it operates. Visitor 允许您定义一个新操作,而无需更改它所操作的元素的类。
Use Visitor pattern if:在以下情况下使用访客模式:
Even though Visitor pattern provides flexibility to add new operation without changing the existing code in Object, this flexibility has come with a drawback.尽管访问者模式提供了在不更改对象中现有代码的情况下添加新操作的灵活性,但这种灵活性也有一个缺点。
If a new Visitable object has been added, it requires code changes in Visitor & ConcreteVisitor classes.如果添加了新的 Visitable 对象,则需要更改 Visitor 和 ConcreteVisitor 类中的代码。 There is a workaround to address this issue: Use reflection, which will have impact on performance.有一种解决方法可以解决此问题:使用反射,这会对性能产生影响。
Refer to oodesign article and sourcemaking articles for more details有关详细信息,请参阅oodesign 文章和sourcemaking文章
Strategy pattern intent:策略模式意图:
Define a family of algorithms, encapsulate each one, and make them interchangeable.定义一系列算法,封装每个算法,并使它们可以互换。 Strategy lets the algorithm vary independently from the clients that use it.策略让算法独立于使用它的客户而变化。
Strategy lets you change the guts of an object.策略让你改变一个对象的内脏。
Refer to below SE questions for more details:有关详细信息,请参阅以下 SE 问题:
Visitor pattern is used to traverse the object hierarchy and provide some functionality like printing or reporting etc., I used this to provide different formats (Text/HTML) to print an object hierarchy by writing multiple visitors, one for each format.访问者模式用于遍历对象层次结构并提供一些功能,如打印或报告等,我用它来提供不同的格式(文本/HTML),通过编写多个访问者来打印对象层次结构,每种格式一个。 The objects in the hierarchy are the visitables.层次结构中的对象是可访问对象。
Strategy pattern is used to pick a particular logical path based on the input.策略模式用于根据输入选择特定的逻辑路径。 A classic example is authentication filters where based on the value in the Authorization
HTTP header, different authentication strategies like NTLM/Negotiate/Basic are picked and run.一个典型的例子是身份验证过滤器,其中基于Authorization
HTTP 标头中的值,选择并运行不同的身份验证策略,如 NTLM/Negotiate/Basic。 The filter would hold a reference to the AuthenticationStrategy interface, based on the incoming request, a particular authentication strategy is picked and assigned to this reference and the code that follows doesn't need to know the exact strategy being used.过滤器将持有对 AuthenticationStrategy 接口的引用,基于传入的请求,选择特定的身份验证策略并将其分配给该引用,并且随后的代码不需要知道所使用的确切策略。
Visitor is for when you have a family of classes and you need to add new functionality to every class in that family but not touch the classes themselves (or wish to have that new functionality all defined in one place - the visitor)访问者适用于当你有一个类家族并且你需要向该家族中的每个类添加新功能但不接触类本身(或者希望在一个地方定义所有新功能 - 访问者)
Strategy is for when you have a family of classes that need to be able to do something in order to work properly (such as sort some objects they contain) but you want the client or your dependancy injection to tell them which way to go about doing that.策略适用于当你有一系列类需要能够做一些事情才能正常工作时(例如对它们包含的一些对象进行排序)但你希望客户端或你的依赖注入告诉他们采取哪种方式去做那。
In addition to the behavioural difference mentioned above, I also experienced a difference regarding the dependencies and use cases during a project once I was working on, like the following.除了上面提到的行为差异外,我在进行项目时还遇到了有关依赖项和用例的差异,如下所示。
For example, Visitor knows about concrete classes.例如,Visitor 了解具体类。 So you will be more flexible at the expense of changing your visitor code as you add new concrete classes to the hierarchy.因此,在向层次结构中添加新的具体类时,以更改访问者代码为代价,您将更加灵活。 There's no such thing in Strategy.战略中没有这样的东西。 In this context, Strategy becomes more suitable if you've methods only to return some output with a given input, regardless of the context.在这种情况下,如果您的方法只是通过给定的输入返回一些输出,而不管上下文如何,那么 Strategy 就变得更合适了。
Moreover, Visitor pattern also used to implement SRP of SOLID, to separate concerns.此外,访问者模式还用于实现 SOLID 的 SRP,以分离关注点。
Imagine you are building a cash register app that's building receipts.想象一下,您正在构建一个正在构建收据的收银机应用程序。 And let's say you want to:假设您想:
1. ensure that different kind of items (books, fruit, meat, toiletries etc) are being processed differently 1. 确保对不同种类的物品(书籍、水果、肉类、洗漱用品等)进行不同的处理
2. keep the logic of actual calculation of the price separately from the item definitions 2. 将实际计算价格的逻辑与项目定义分开
3. ensure that if the shop starts selling something completely new (let's say cloth that will be charged by length), you won't have to change too many codes 3.确保如果商店开始销售全新的东西(比方说按长度收费的布料),你不必更改太多代码
Visitor could be a class that defines different kinds of calculations depending on what kind of item is being processed.访问者可以是一个类,它根据正在处理的项目类型定义不同类型的计算。 It's a service that moves away the differences in price calculations away from the hierarchy of items.这是一项将价格计算差异从项目层次结构中移开的服务。
where the body of getPrice
could look like this: getPrice
的正文可能如下所示:
getPrice(Calculation c) {
return c.calculate(this); // <-- visitor.visit( specific implementation )
}
and in say ShoppingCart
you will do:在说ShoppingCart
中,您将执行以下操作:
calc = getPriceCalculator()
foreach item in items:
totalPrice += item.getPrice(calc)
Imagine this scenario: On Black Friday you want to do some crazy discounts, 70% off of all books, 50% off of all fruit.想象一下这个场景:在黑色星期五,你想做一些疯狂的折扣,所有书籍都打折 70%,所有水果都打折 50%。 You can easily do something along the lines:你可以很容易地做一些事情:
BlackFridayCalculator extends PriceCalculator {
calculate(Book b) { return 0.3 * parent.calculate(b) }
calculate(Fruit f) { return 0.5 * parent.calculate(f) }
}
// and in getPriceCalculator:
return (black friday time) ? new BlackFridayCalculator() : new PriceCalculator();
Strategy instead could have a hierarchy of a different kind of calculations (strategies) and each item would then define, which calculation (strategy) should be used ("plugged").相反,策略可以具有不同类型的计算(策略)的层次结构,然后每个项目将定义应该使用哪种计算(策略)(“插入”)。
Now there are many ways how to define which item should use which calculation.现在有很多方法可以定义哪个项目应该使用哪个计算。 The most straightforward would be giving Item
method getCalculator
and let each item choose which calculation it needs.最直接的方法是提供Item
方法getCalculator
并让每个项目选择它需要的计算。
This might be a bit less dynamic - in a sense that each item needs to have a predefined calculator that will be used.这可能有点不那么动态——从某种意义上说,每个项目都需要有一个预定义的计算器来使用。 But think of this scenario: Owner of the shop decides that pineapples and watermelons should be sold per piece - we can easily let Fruit
use WeightCalculator
by default and create a subset of fruit that will be sold by quantity.但是想想这个场景:店主决定菠萝和西瓜应该按件出售——我们可以很容易地让Fruit
默认使用WeightCalculator
并创建一个按数量出售的水果子集。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.