设计模式:提取常用功能

时间:2014-09-04 17:56:45

标签: design-patterns

我有以下代码。我有两个不同的工作,它们调用相同的下面提到的处理器类。这两项工作几乎完全相同,但仅在最后一步有所不同。目前,我正在基于布尔变量' createReport'来处理它。我想将90%的常用功能提取到一个类中。

我想到了模板模式。但是我如何在抽象类中注入repositoryA的依赖?

Imports log4net
Imports System
Imports System.Collections.Generic

Public Interface IProcessor
    Sub Process(path As String, includeCache As Boolean, createReport As Boolean)
End Interface

Public Class Processor
    Implements IProcessor

    Private ReadOnly _repositoryA As IRepositoryA
    Private ReadOnly _repositoryB As IRepositoryB
    Private ReadOnly _logger As ILog

    Public Sub New(repositoryA As IRepositoryA, repositoryB As IRepositoryB, logger As ILog)
        If repositoryA Is Nothing Then
            Throw New ArgumentNullException("repositoryA")
        End If

        If repositoryB Is Nothing Then
            Throw New ArgumentNullException("repositoryB")
        End If

        If logger Is Nothing Then
            Throw New ArgumentNullException("logger")
        End If

        _repositoryA = repositoryA
        _repositoryB = repositoryB
        _logger = logger
    End Sub

    Public Sub Process(folderPaths As String, includeCache As Boolean, createReport As Boolean) Implements IProcessor.Process
        _logger.Info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")

        If String.IsNullOrEmpty(folderPaths) Then
            Throw New ArgumentNullException("folderPaths")
        End If

        Dim paths() As String = folderPaths.Split(New Char() {";"c})
        For Each path As String In paths
            Dim cList As List(Of Container) = _repositoryA.GetContainers(path, includeCache)
            For Each container As Container In cList
                If Not container.IsDeleted Then
                    Dim assetList As List(Of Asset) = _repositoryA.GetAssets(container.ContainerID)
                    If Not assetList Is Nothing Then
                        For Each asset As Asset In assetList
                            ProcessAsset(asset, createReport)
                        Next
                    End If
                End If
            Next
        Next

        _logger.Info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
    End Sub

    Private Sub ProcessAsset(asset As Asset, createReport As Boolean)
        'Again some common business logic

        'at last depending on value of createReport
        If createReport Then
            CreateReport(asset)
        Else
            SyncAsset(asset, ...other arguments)
        End If
    End Sub

    Private Sub SyncAsset(asset As asset, ..other arguments)
        'business logic. Dependency on _repositoryB here
    End Sub

    Private Sub CreateReport(asset As asset)
        'business logic
    End Sub
End Class

感谢您的帮助

此致 Suyog

1 个答案:

答案 0 :(得分:1)

我会将您的Process方法划分为表达您希望代码遵循的流程的不同类。然后将抽象背后的类传递给主算法,这样就可以动态地交换部分行为。

在这种情况下,您希望列出资产并处理每个资产。该过程执行N次操作并最终确定资产(即,同步它创建报告)。让我们将它分解为我们可以使用的子组件/接口:

  • IAssetListCreator {IEnumerable CreateAssetList();}
  • IAssetProcessor {void Process(Asset a,IAssetFinalizer af);}
  • IAssetFinalizer {void Finalize(Asset a);}

现在你可以编写不同的砖块来复制你以前的算法:

Public Interface IProcessor
    Sub Process(creator as IAssetListCreator, processor as IAssetProcessor, finalizer as IAssetFinalizer)
End Interface

' inside the process class
Public Sub Process(creator as IAssetListCreator, processor as IAssetProcessor, finalizer as IAssetFinalizer) Implements IProcessor.Process
     _logger.Info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")

  For Each asset As Asset In creator.CreateAssetList()
      processor.Process(asset, finalizer)
    Next

    _logger.Info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
End Sub

' inside the IAssetProcessor
Private Sub ProcessAsset(asset As Asset, finalizer as IAssetFinalizer)
    'Again some common business logic
    finalizer.Finalize(asset)
End Sub

现在可以仅使用所需的元素构造每个组件:如果仅在同步行为中需要repositoryA,则创建一个继承自IAssetFinalizer的类,该类在构造函数中使用repositoryA。本着同样的精神,只有IAssetListCreator实例需要知道资产所在的路径,或者是否应该涉及缓存等......

我在打破原始代码方面全力以赴;您仍然可以使用Process函数中的列表代码,但您确实可以将参数限制为需要它们的组件: