gpt4 book ai didi

design-patterns - 访客vs仆人vs命令模式

转载 作者:行者123 更新时间:2023-12-04 06:59:48 24 4
gpt4 key购买 nike

Here讨论了命令和仆人模式的相似之处。但是另一方面,我看到Servant与Visitor非常相似,而且非常相似,我根本不知道有什么区别?两者都通过添加功能来服务于其他类对象。但是命令模式不添加功能,而是包装功能,对吗?请解释我的困惑在哪里。

最佳答案

我将尽力描述我对此事的看法和理解,也许我们可以对此进行进一步讨论。

命令:如您所写-它包装了功能。
除功能外,它还保留了应用该方法时要操作的数据和要传递的参数。

该命令的Execute方法知道如何将所有部分组合在一起以完成工作。

因此,我将命令视为自主工作的容器。以后可以存储并执行。

仆人:这是一种简单的模式,其重点是通过将仆人(或客户阶级)的职责(责任)排除在仆人或助手阶级之外来减轻其责任。

指挥官与仆人之间的区别

时间分隔-命令是自主容器,可以存储/排队/排序或调度,并且可以在以后的时间执行。
同样,命令模式遵循更黑盒的编程模型,因为命令的调用者只需要调用'Execute'函数。

因此,一个命令可以由一个类创建,而由另一个类调用。

访客模式及其差异

我将以一个例子来说明差异-

假设我有3种类型的移动设备-iPhone,Android,Windows Mobile。

所有这三个设备都安装了蓝牙无线电。

假设蓝牙无线电可以来自两个独立的OEM:英特尔和Broadcom。

只是为了使示例与我们的讨论相关,我们还假设英特尔无线电公开的API与Broadcom无线电公开的API不同。

这是我班级的样子–

enter image description here

enter image description here

现在,我要介绍一个操作–在移动设备上打开蓝牙。

它的功能签名应该像这样–

 void SwitchOnBlueTooth(IMobileDevice mobileDevice, IBlueToothRadio blueToothRadio)


因此,根据设备的正确类型和蓝牙无线电的正确类型,可以通过调用适当的步骤或算法将其打开。

原则上,它变成一个3 x 2的矩阵,其中,我试图根据所涉及对象的正确类型对正确的操作进行矢量化处理。

多态行为取决于两个参数的类型。 enter image description here

因此,正如Wiki页面在“动机”部分所说的那样,解决此类问题的幼稚方法会遇到很多问题。

现在,我将向访客介绍此问题的模式。灵感来自维基百科页面:“本质上,访问者允许一个人向一类类添加新的虚函数,而无需修改类本身;而是创建一个访问者类,该类实现虚拟函数的所有适当专业化。访问者将实例引用作为输入,并通过双重调度实现目标。”

由于采用3x2矩阵,因此必须进行双重调度

在代码中引入访客模式-

我必须先做出决定,哪个类层次结构更稳定(不易更改)–设备类层次结构或蓝牙类层次结构。
一种更稳定的将成为可访问的班级,而另一种稳定的将成为访问者的班级。在本例中,我将说设备类更稳定。

这是设置

enter image description here

这是客户代码和测试代码

 class Client
{
public void SwitchOnBlueTooth(IMobileDevice mobileDevice, IBlueToothVisitor blueToothRadio)
{
mobileDevice.TurnOn(blueToothRadio);
}
}


[TestClass]
public class VisitorPattern
{

Client mClient = new Client();

[TestMethod]
public void AndroidOverBroadCom()
{
IMobileDevice device = new Android();
IBlueToothVisitor btVisitor = new BroadComBlueToothVisitor();

mClient.SwitchOnBlueTooth(device, btVisitor);
}

[TestMethod]
public void AndroidOverIntel()
{
IMobileDevice device = new Android();
IBlueToothVisitor btVisitor = new IntelBlueToothVisitor();

mClient.SwitchOnBlueTooth(device, btVisitor);
}

[TestMethod]
public void iPhoneOverBroadCom()
{
IMobileDevice device = new iPhone();
IBlueToothVisitor btVisitor = new BroadComBlueToothVisitor();

mClient.SwitchOnBlueTooth(device, btVisitor);
}

[TestMethod]
public void iPhoneOverIntel()
{
IMobileDevice device = new iPhone();
IBlueToothVisitor btVisitor = new IntelBlueToothVisitor();

mClient.SwitchOnBlueTooth(device, btVisitor);
}
}


这是类的层次结构

     /// <summary>
/// Visitable class interface
/// </summary>
interface IMobileDevice
{
/// <summary>
/// It is the 'Accept' method of visitable class
/// </summary>
/// <param name="blueToothVisitor">Visitor Visiting the class</param>
void TurnOn(IBlueToothVisitor blueToothVisitor);
}

class iPhone : IMobileDevice
{
public void TurnOn(IBlueToothVisitor blueToothVisitor)
{
blueToothVisitor.SwitchOn(this);
}
}

class Android : IMobileDevice
{
public void TurnOn(IBlueToothVisitor blueToothVisitor)
{
blueToothVisitor.SwitchOn(this);
}
}

class WindowsMobile : IMobileDevice
{
public void TurnOn(IBlueToothVisitor blueToothVisitor)
{
blueToothVisitor.SwitchOn(this);
}
}

interface IBlueToothRadio
{

}

class BroadComBlueToothRadio : IBlueToothRadio
{

}

class IntelBlueToothRadio : IBlueToothRadio
{

}


访客跟随-

/// <summary>
/// Wiki Page - The Visitor pattern encodes a logical operation on the whole hierarchy into a single class containing one method per type.
/// </summary>
interface IBlueToothVisitor
{
void SwitchOn(iPhone device);
void SwitchOn(WindowsMobile device);
void SwitchOn(Android device);
}


class IntelBlueToothVisitor : IBlueToothVisitor
{
IBlueToothRadio intelRadio = new IntelBlueToothRadio();

public void SwitchOn(iPhone device)
{
Console.WriteLine("Swithing On intel radio on iPhone");
}

public void SwitchOn(WindowsMobile device)
{
Console.WriteLine("Swithing On intel radio on Windows Mobile");
}

public void SwitchOn(Android device)
{
Console.WriteLine("Swithing On intel radio on Android");
}
}

class BroadComBlueToothVisitor : IBlueToothVisitor
{
IBlueToothRadio broadCom = new BroadComBlueToothRadio();

public void SwitchOn(iPhone device)
{
Console.WriteLine("Swithing On BroadCom radio on iPhone");
}

public void SwitchOn(WindowsMobile device)
{
Console.WriteLine("Swithing On BroadCom radio on Windows Mobile");
}

public void SwitchOn(Android device)
{
Console.WriteLine("Swithing On BroadCom radio on Android");
}
}


让我先介绍一下此结构的某些要点,然后再介绍仆人模式–


我有2位Bluetooth访问者,其中包含在每种类型的移动设备上开启Bluetooth的算法
我将BluetoothVistor和BluetoothRadio分开,以坚持访问者的理念–“在不修改类的情况下添加操作”。也许其他人希望将其合并到BluetoothRadio类本身中。
每个访问者都定义了3种功能-每种类型的移动设备都需要一种。 (这与Servant模式有很大的不同– Servant模式应该为所有服务的类仅提供一种算法。)
同样在这里,由于存在6种算法变体(取决于对象的类型),因此必须进行双重调度。在仆人模式中,我们仅讨论算法的单个变体。
正如我上面所写的那样,我最初的要求是具有这样的功能- void SwitchOnBlueTooth(IMobileDevice mobileDevice, IBlueToothRadio blueToothRadio),现在为了使双重调度正常工作,我更改了签名–我使用的是 IBlueToothRadio而不是 IBlueToothVisitor


现在,让我们看一下相同的情况并实现Servant模式。

仆人模式是一种更为简单的模式,它的目的只是从类的层次结构中提取出通用的功能,以使其在所有类中都不重复。

为此,我们假设所有3个设备都需要完全相同的算法来开启蓝牙。
另外,我们假设只存在一种无线电。

现在,我们可以在所有三个设备类中编写相同的算法,也可以按照Wiki所述应用仆人模式-“ Servant用于向一组类提供某些行为。不必在每个类中定义该行为-或当我们无法在公共父类中排除该行为时-只能在仆人中定义一次。”

enter image description here

我已经指出了与红色圆圈的区别


无需双重调度,客户可以直接致电
服务阶层的仆人
适用于所有3种设备的单一算法


这是客户端(这是唯一处理分派的地方)和测试代码

class Client
{
public void SwitchOnBlueTooth(IMobileDevice mobileDevice, IBlueToothServant blueToothRadio)
{
//there is just one BT servant & all the serviced types get the same service (No There is no specificity).
// Wiki page - User knows the servant (in which case he doesn’t need to know the serviced classes) and sends messages with his requests to the servant instances, passing the serviced objects as parameters.
blueToothRadio.SwitchOn(mobileDevice);
}
}


[TestClass]
public class ServantPattern
{

Client mClient = new Client();

[TestMethod]
public void AndroidBlueToothOn()
{
IMobileDevice device = new Android();
IBlueToothServant btServant = new BlueToothServant();

mClient.SwitchOnBlueTooth(device, btServant);
}

[TestMethod]
public void iPhoneOverBroadCom()
{
IMobileDevice device = new iPhone();
IBlueToothServant btServant = new BlueToothServant();

mClient.SwitchOnBlueTooth(device, btServant);
}

[TestMethod]
public void WMBlueToothOn()
{
IMobileDevice device = new WindowsMobile();
IBlueToothServant btServant = new BlueToothServant();

mClient.SwitchOnBlueTooth(device, btServant);
}
}


服务类层次结构在这里没有那么有趣

/// <summary>
/// Serviced class interface
/// </summary>
interface IMobileDevice
{

}

class iPhone : IMobileDevice
{

}

class Android : IMobileDevice
{
}

class WindowsMobile : IMobileDevice
{
}


这是服务方类及其接口(Wiki链接未显示其接口)

 /// <summary>
/// The sevant interface
/// </summary>
/// <remarks>Not present in Wiki article but I have added so its easy to mock it</remarks>
interface IBlueToothServant
{
void SwitchOn(IMobileDevice device);
}


class BlueToothServant : IBlueToothServant
{
IBlueToothRadio intelRadio = new BlueToothRadio();

public void SwitchOn(IMobileDevice device)
{
Console.WriteLine("Switching On blue tooth radio on IMobileDevice");
}

}


我没有粘贴 IBlueToothRadioBlueToothRadio的代码,因为这与讨论仆人模式不太相关。

请让我知道是否有任何不清楚的地方,我们可以进一步讨论。

关于design-patterns - 访客vs仆人vs命令模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31986332/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com