Oop 战略模式和访客模式有什么区别?
我很难理解这两种设计模式 你能给我一个上下文信息或者一个例子,这样我就可以得到一个清晰的想法,并且能够映射出两者之间的差异 谢谢Oop 战略模式和访客模式有什么区别?,oop,design-patterns,strategy-pattern,visitor-pattern,Oop,Design Patterns,Strategy Pattern,Visitor Pattern,我很难理解这两种设计模式 你能给我一个上下文信息或者一个例子,这样我就可以得到一个清晰的想法,并且能够映射出两者之间的差异 谢谢 它们的区别是: 动机 意图 实施 不知道比较两种不同的东西能得到什么,但要比较一下 这两种方法有什么相同之处,可以让一个人看到它们的不同之处?一种策略模式用于将各种算法公开到一个标准化的界面。一个典型的例子是排序实用程序,它允许用户(程序员)在通过同一接口调用的各种排序算法之间进行选择 访问者模式处于不同的级别。它详细介绍了一种机制,通过该机制,对象可以接受对另一个
它们的区别是:
这两种方法有什么相同之处,可以让一个人看到它们的不同之处?一种策略模式用于将各种算法公开到一个标准化的界面。一个典型的例子是排序实用程序,它允许用户(程序员)在通过同一接口调用的各种排序算法之间进行选择 访问者模式处于不同的级别。它详细介绍了一种机制,通过该机制,对象可以接受对另一个对象(访问者)的引用,该对象公开了目标对象可以调用自己的预定接口。当然,不同的访问者会呈现相同的界面,但有不同的实现 回到我们的示例,可以通过Strategy模式或Visitor模式实现一组排序算法 在策略方法中,每种算法都提供相同的接口,并以目标对象数组为参数。对于访问者模式,目标数组将使用“访问者”算法作为参数。在本例中,目标将“接受()”所选访问者,并在我们的示例中调用目标的sort方法时调用其“visit()”方法 同一枚硬币的两面
这有意义吗?战略模式就像一种1:many关系。当存在一种类型的对象并且我想对其应用多个操作时,我使用策略模式。例如,如果我有一个封装视频剪辑的视频类,我可能希望以不同的方式压缩它。因此,我创建了一系列策略类:
MpegCompression
AviCompression
QuickTimeCompression
等等
我认为访客模式是一种多:多关系。假设我的应用程序不仅包括视频,还包括音频剪辑。如果我坚持策略模式,我必须复制我的压缩类——一个用于视频,一个用于音频:
MpegVideoCompression
MpegAudioCompression
等等
如果切换到访问者模式,则不必复制策略类。我通过添加以下方法来实现我的目标:
MpegCompressionVisitor::compressVideo(Video object)
MpegCompressionVisitor::compressAudio(Audio object)
[更新:使用Java]
我在Java应用程序中使用了访问者模式。结果与上面描述的略有不同。下面是这个示例的Java版本
//访问者界面
接口压缩器{
//访客方法
void压缩(视频对象);
无效压缩(音频对象)
}
//访问者实现
类MpegCompressor执行压缩机{
公共空压缩(视频对象){
System.out.println(“Mpeg视频压缩”);
}
公共空压缩(音频对象){
...
}
}
现在是要访问的接口和类:
界面可压缩{
无效接受(压缩机);
}
类视频实现可压缩{
//如果压缩机是MpegCompressionVisitor的实例,
//系统打印“Mpeg视频压缩”
无效接受(压缩机){
压缩(这个);
}
定义上的区别在于,访问者使用运算符重载为元素的子类提供了不同的行为。它知道自己正在处理或访问的内容
同时,一个策略将在其所有实现中保持一致的接口
访问者用于允许对象的子部分使用一致的方法来做某事。策略用于允许如何做某事的依赖项注入
因此,这将是一位访客:
class LightToucher : IToucher{
string Touch(Head head){return "touched my head";}
string Touch(Stomach stomach){return "hehehe!";}
}
用另一个这种类型的
class HeavyToucher : IToucher{
string Touch(Head head){return "I'm knocked out!";}
string Touch(Stomach stomach){return "oooof you bastard!";}
}
我们有一个类,它可以使用这个访问者来完成它的工作,并根据它进行更改:
class Person{
IToucher visitor;
Head head;
Stomach stomach;
public Person(IToucher toucher)
{
visitor = toucher;
//assume we have head and stomach
}
public string Touch(bool aboveWaist)
{
if(aboveWaist)
{
visitor.Touch(head);
}
else
{
visitor.Touch(stomach);
}
}
}
所以如果我们这样做
var person1=新人(new LightToucher());
var person2=新人(new HeavyToucher())
对我来说,第二个图形似乎是访问者模式……因为对于策略模式,类包含的数据结构往往只有一个,没有子类(或者子类保持与此部分相同的行为)。策略用于同一结构上的不同操作。我认为策略模式是将方法/策略注入对象的一种方式,但通常该方法的签名采用一些值参数并返回一个结果,因此它不会与策略的用户耦合: 发件人: 取而代之的是,访问者通过双重分派和用户耦合,并且通常保持状态。 很好的例子,我将从那里复制:
public class BlisterPack
{
// Pairs so x2
public int TabletPairs { get; set; }
}
public class Bottle
{
// Unsigned
public uint Items { get; set; }
}
public class Jar
{
// Signed
public int Pieces { get; set; }
}
public class PillCountVisitor : IVisitor
{
public int Count { get; private set; }
#region IVisitor Members
public void Visit(BlisterPack blisterPack)
{
Count += blisterPack.TabletPairs * 2;
}
public void Visit(Bottle bottle)
{
Count += (int) bottle.Items;
}
public void Visit(Jar jar)
{
Count += jar.Pieces;
}
#endregion
}
public class BlisterPack : IAcceptor
{
public int TabletPairs { get; set; }
#region IAcceptor Members
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
#endregion
}
正如您所看到的,访问者具有state(public int Count),并且它在已知类型的列表上运行。因此,如果您想要支持一个新类型,您需要通过添加该类型来更改所有访问者
此外,由于“visitor.Visit(this);”的原因,它还与它所操作的类型相结合。如果我删除或更改“Items”,会发生什么情况属性表单瓶子?…所有访问者都会失败。访问者就像一夜情一样-当您调用accept函数时创建它,然后它们会分离,访问者可以从内存中清除,使用它的类不会占用任何空间 这个策略就像一场婚姻——你创建了一个对象,它生活在使用它的班级里,占用了记忆,有一个房间,早上自己煮咖啡:)。 当然,他们可以离婚,换到另一个阶级,但这个阶级也会生活在它主人的环境中
希望它能帮助您记住:)如果您只有一个上下文或元素,并且需要在该上下文上执行不同的操作,那么您可以
class Minus : ICalculateStrategy {
public int Calculate(int value1, int value2) {
return value1 - value2;
}
}
public class BlisterPack
{
// Pairs so x2
public int TabletPairs { get; set; }
}
public class Bottle
{
// Unsigned
public uint Items { get; set; }
}
public class Jar
{
// Signed
public int Pieces { get; set; }
}
public class PillCountVisitor : IVisitor
{
public int Count { get; private set; }
#region IVisitor Members
public void Visit(BlisterPack blisterPack)
{
Count += blisterPack.TabletPairs * 2;
}
public void Visit(Bottle bottle)
{
Count += (int) bottle.Items;
}
public void Visit(Jar jar)
{
Count += jar.Pieces;
}
#endregion
}
public class BlisterPack : IAcceptor
{
public int TabletPairs { get; set; }
#region IAcceptor Members
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
#endregion
}
Applying a very generic and abstract repair