具有依赖关系的命令模式

时间:2016-02-26 18:46:29

标签: vb.net design-patterns architecture

我是一个老的VB6开发人员,我正在尝试学习一些OOP方法。我正在开发一个Winforms应用程序,该应用程序具有多个在应用程序生命周期内存在的对象,例如与其他计算机上运行的应用程序的日志记录,音频和套接字连接。某些事情(如按下按钮或接收到的消息)可以触发与一个或多个这些对象相关的操作。例如,当用户单击“登录”按钮时,我可能希望将其记录到文件,打开套接字连接,向用户播放音频以及启动麦克风。看起来Command模式可能会做我想要的,但是当有这么多时,我如何干净地传递依赖关系呢?所以它可能看起来像:

Public Interface ICommand
    Sub Execute()
End Interface

Public Class LoginCommand
    Implements ICommand

    Protected _Receiver As LoginCommandReceiver

    Public Sub New(Receiver As LoginCommandReceiver)
        _Receiver = Receiver
    End Sub

    Public Sub Execute() Implements ICommand.Execute
        _Receiver.Login()
    End Sub
End Class

Public Class LoginCommandReceiver
    Protected _Logger As LogManager
    Protected _Gateway As IGatewayConnection
    Protected _Audio As IAudioPlayer
    Protected _VR As IVREngine

    Public Sub New(Logger As LogManager, Gateway As IGatewayConnection, Audio As IAudioPlayer, VR As IVREngine)
        _Logger = Logger
        _Audio = Audio
        _Gateway = Gateway
        _VR = VR
    End Sub

    Public Sub Login()
        _Logger.LogEvent("Starting login")

        _Audio.PlayRingtone()
        _Gateway.Connect()
        _VR.Start()

        _Logger.LogEvent("Login complete")
    End Sub
End Class

现在,即使在这个简单的例子中,LoginCommandReceiver的构造函数也变得混乱了。我想过将所需的依赖项放入容器类中。然后构造函数可以如下所示:

Public Sub New(Container As ApplicationContainer)
    With Container
        _Logger = .Logger
        _Audio = .Audio
        _Gateway = .Gateway
        _VR = .VR
    End With
End Sub

我实际上已经构建了这个容器类(没有Command模式)但是容器类变得非常大(差不多30个对象),并且将这个巨大的东西传递给只需要一个的类是不对的。它包含的部分。服务定位器模式似乎是合适的,但我正在阅读,应该避免。

我还考虑过将每个步骤作为自己的命令,如LogCommand,PlayRingtoneCommand,GatewayConnectCommand和VRStartCommand。然后每个子命令只需要知道一个应用程序级对象。例如,播放铃声只需要知道音频对象:

Public Class PlayRingtoneCommand
    Implements ICommand

    Protected _Receiver As PlayRingtoneCommandReceiver

    Public Sub New(Receiver As PlayRingtoneCommandReceiver)
        _Receiver = Receiver
    End Sub

    Public Sub Execute() Implements ICommand.Execute
        _Receiver.PlayRingtone()
    End Sub
End Class

Public Class PlayRingtoneCommandReceiver
    Protected _Audio As IAudioPlayer

    Public Sub New(Audio As IAudioPlayer)
        _Audio = Audio
    End Sub

    Public Sub PlayRingtone()
        _Audio.PlayRingtone()
    End Sub
End Class

现在每个命令在其构造函数中都有一个对象,它更干净。但在某个地方,有人仍然必须知道所有对象才能创建命令列表。在制作这个巨型容器之外,我将所有对象实例放在一起的另一个时间是在程序启动时我将所有连接在一起。我是否需要在此时创建所有命令类型的实例?可能会有很多。或者是否有其他设计可以使这个更干净?

0 个答案:

没有答案