2014-09-04 69 views
0

我有以下代码。我有两个不同的工作,它们调用下面提到的处理器类。这两项工作几乎完全相同,但只有在最后一步才会有所不同。目前,我正在基于布尔变量'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

+0

请使用语法高亮显示 – 2014-09-04 18:51:40

+0

我没有看到问题。模板方法听起来像一个合理的方法。什么阻止你在抽象类中定义存储库变量? – 2014-09-05 07:23:44

回答

1

我会分裂在表达流不同类别的Process方法,你希望你的代码遵循。然后将这些类传递到主算法的后面,这样您就可以动态地替换部分行为。

在这种情况下,您希望列出资产并处理每项资产。该过程执行N次操作并完成资产(即或者同步创建报告)。让我们把它分解成子/界面,我们可以使用:

  • IAssetListCreator {IEnumerable的CreateAssetList();}
  • IAssetProcessor {无效处理(资产一,IAssetFinalizer AF);}
  • IAssetFinalizer {无效敲定(一资产);}

现在你可以撰写不同的砖块,以复制你有算法之前:

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,则创建一个继承自使用构造函数中的repositoryA的IAssetFinalizer的类。本着同样的精神,只有IAssetListCreator实例需要了解资产所在的路径,或者是否应该涉及缓存等等。

我全速前进,打破原始代码;您仍然可以使用Process函数中的列表代码,但是您真正受益于将参数限制为需要它们的组件: