Here讨论了Command和Servant模式的相似之处。但另一方面,我发现仆人与访客非常相似,而且非常相似,我根本不知道有什么区别?两者都通过添加功能为其他类对象服务。但命令模式不会添加功能,而是包装它,对吧?请解释我的困惑在哪里。
答案 0 :(得分:11)
我试着描述一下我的观点&对此事的理解,也许我们可以进一步讨论它。
命令:正如您所写 - 它包含了一项功能。 除了功能之外,它还包含要操作的数据以及应用该方法时要传递的参数。
命令的Execute
方法知道如何将所有部分组合在一起以完成工作。
因此,我将命令看作是一个自主的工作容器。哪个可以存储&稍后执行。
Servant:它是一个简单的模式,专注于通过在服务员或帮助者类中承担(责任)来减轻Master类(或客户端类)的职责。
Command&仆人
时间分离 - 作为自治容器的命令,可以存储/排队/排序或安排,并可以在以后的时间执行。
此外,命令模式遵循更黑盒编程模型,因为命令的调用者只需要调用' Execute
'功能。
所以一个命令可以由一个班级和一个班级创建。被另一个人引用。
访客模式及其差异
我将举例说明差异 -
我们说我有3种类型的移动设备 - iPhone,Android,Windows Mobile。
所有这三款设备都安装了蓝牙无线电。
让我们假设蓝牙收音机可以来自两个独立的原始设备制造商 - 英特尔&博通。
为了使这个例子与我们的讨论相关,我们还假设英特尔无线电公开的API与Broadcom无线电公开的API不同。
这是我的课程的样子 -
现在,我想介绍一项操作 - 在移动设备上打开蓝牙。
它的功能签名应该是这样的 -
void SwitchOnBlueTooth(IMobileDevice mobileDevice, IBlueToothRadio blueToothRadio)
因此,根据正确类型的设备和取决于正确类型的蓝牙无线电,可以通过调用适当的步骤或算法<来启用它/ strong>即可。
原则上,它变成一个3 x 2矩阵,其中我试图根据所涉及的对象的正确类型来引导正确的操作。
正如维基页面在“动机”部分所述,解决此类问题的一种天真的方式会遇到很多问题。
现在,我将介绍此问题的访问者模式。灵感来自维基百科页面说明 - “实质上,访问者允许一个人在不修改类本身的情况下向一个类族添加新的虚函数;相反,我们创建了一个访问者类,它实现了虚函数的所有适当的特化。访问者将实例引用作为输入,并通过双重调度实现目标。“
由于3x2矩阵
,双重调度是必要的在代码中引入访客模式 -
我必须先做出决定,哪个类层次结构更稳定(不易改变) - 设备类层次结构或蓝牙类层次结构。 一个更稳定的将成为可访问的类和&amp;不太稳定的人将成为访客班级。对于这个例子,我会说设备类更稳定。
这是设置
这是客户代码&amp;测试代码
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");
}
}
在进入仆人模式之前,让我先谈谈这个结构的一些要点 -
void SwitchOnBlueTooth(IMobileDevice mobileDevice, IBlueToothRadio blueToothRadio)
,现在我已经改变了签名的双重调度 - 而不是IBlueToothRadio
我使用IBlueToothVisitor
现在让我们看一下同样的情况&amp;让我们实施Servant模式。
Servant模式是一种更简单的模式,它只是旨在从类的层次结构中取出共同的功能,以便它们不会在所有类中重复。
为此,我们假设所有3台设备都需要完全相同的算法才能打开蓝牙。 此外,我们假设只存在一种类型的无线电。
现在我们可以在所有3个设备类中编写相同的算法,或者我们可以应用servant模式,因为wiki说 - “Servant用于为一组类提供一些行为。不是在每个类中定义该行为 - 或者当我们不能在公共父类中分解出这种行为时 - 它在Servant中定义一次。“
我已经指出与红圈的区别
这是客户端(这是处理调度的唯一地方)&amp;测试代码
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
{
}
这里是仆人班&amp;它的界面(维基链接没有显示它的界面)
/// <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");
}
}
我没有粘贴IBlueToothRadio
&amp;的代码BlueToothRadio
因为这与讨论仆人模式不太相关。
如果不清楚我们可以进一步讨论,请告诉我。