代码之家  ›  专栏  ›  技术社区  ›  CrimsonX

对象设计:如何组织/构造“集合类”

  •  3
  • CrimsonX  · 技术社区  · 15 年前

    1. 在构造函数中,它通过一系列实现我的业务逻辑的算法来验证和过滤日志
    2. 所有过滤和验证完成后,它返回一个有效和过滤日志的集合(列表),可以在UI中以图形方式呈现给用户。

    class FilteredCollection
    {
      public FilteredCollection( SpecialArray<MyLog> myLog)
      {   
      // validate inputs
      // filter and validate logs in collection
      // in end, FilteredLogs is ready for access
      }
      Public List<MyLog> FilteredLogs{ get; private set;}
    
    }
    

    但是,为了访问此集合,我必须执行以下操作:

    var filteredCollection = new FilteredCollection( specialArrayInput );
    //Example of accessing data
    filteredCollection.FilteredLogs[5].MyLogData;
    

    1. 我预见到应用程序中只存在一个过滤的集合(因此我应该使它成为一个静态类吗?或者是单身汉?)
    2. 创建对象时的可测试性和灵活性很重要(也许因此我应该将这个类作为可测试性的实例?)
    3. 如果可能的话,我更愿意简化对日志的取消引用,因为实际的变量名相当长,需要60-80个字符才能到达实际的数据。
    4. 我试图使这个类保持简单,因为这个类的唯一目的是创建这个已验证数据的集合。

    我知道这里可能没有“完美”的解决方案,但我真的在努力提高我的设计技能,我会非常感谢这样做的建议。提前谢谢。


    编辑:

    namespace MyNamespace.BusinessLogic.Filtering
    {
        public static class MyLogsFilter
        {
            public static IList<MyLog> Filter(this SpecialArray<MyLog> array)
            {
                // filter and validate logs in collection
                // in end, return filtered logs, as an enumerable
            }
        }
    }
    

    我可以在代码中创建一个只读的集合

    IList<MyLog> filteredLogs = specialArrayInput.Filter(); 
    ReadOnlyCollection<MyLog> readOnlyFilteredLogs = new ReadOnlyCollection<MyLog>(filteredLogs);
    
    4 回复  |  直到 15 年前
        1
  •  1
  •   Dynami Le Savard    15 年前

    在我看来,您看到的是一个返回过滤日志集合的方法,而不是包装业务逻辑的集合类。像这样:

    class SpecialArray<T>
    {
         [...]
    
         public IEnumerable<T> Filter()
         {   
             // validate inputs
             // filter and validate logs in collection
             // in end, return filtered logs, as an enumerable
         }
    
         [...]
    }
    

    但是,看起来您真正希望的是将负责过滤日志的业务逻辑与 SpecialArray 同学们,也许是因为你们觉得逻辑触及了很多其实并不关心的东西 特殊射线 ,或者因为 Filter 特殊射线 .

    在这种情况下,我的建议是将您的业务逻辑隔离在另一个 namespace ,可能使用和/或需要其他组件以应用所述业务逻辑,并将您的功能作为扩展方法,具体如下:

    namespace MyNamespace.Collections
    {
        public class SpecialArray<T>
        {
            // Shenanigans
        }
    }
    
    namespace MyNamespace.BusinessLogic.Filtering
    {
        public static class SpecialArrayExtensions
        {
            public static IEnumerable<T> Filter<T>(this SpecialArray<T> array)
            {
                // validate inputs
                // filter and validate logs in collection
                // in end, return filtered logs, as an enumerable
            }
        }
    }
    

    using MyNamespace.Collections; // to use SpecialArray
    using MyNamespace.BusinessLogic.Filtering; // to use custom log filtering business logic
    namespace MyNamespace
    {
        public static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main2()
            {
                SpecialArray<Logs> logs;
                var filteredLogs = logs.Filter();
            }
        }
    }
    
        2
  •  3
  •   Rob    15 年前

    听起来你对日志做了三件事:

    1. 访问它们

    您希望将日志存储在集合中。标准列表集合非常适合,因为它不关心其中的内容,提供LINQ,并允许您使用只读包装器锁定集合

    考虑

    interface ILog
    {
      MarkAsValid(bool isValid);
      ... whatever data you need to access...
    }
    

    将验证逻辑放在一个单独的接口类中

    interface ILogValidator
    {
      Validate(ILog);
    }
    

    还有你的过滤逻辑

    interface ILogFilter
    {
      Accept(ILog);
    }
    

    然后是LINQ,比如:

    List<MyLog> myLogs = GetInitialListOfLogsFromSomeExternalSystem();
    myLogs.ForEach(x => MyLogValidator(x));
    List<MyLog> myFilteredLogs = myLogs.Where(x => MyLogFilter(x));
    

    关注点的分离使得测试和可维护性更好。远离单身汉。由于许多原因,包括可测试性,它们都不受欢迎。

        3
  •  1
  •   Heinzi    15 年前

    • 如果(A)在整个系统中只有一个类实例,则应该使用单例

    • 对于简单的解引用,请考虑使用 indexer . 这将允许您编写:

        FilteredCollection filteredlogs = new FilteredCollection( secialArrayInput );
        //Example of accessing data
        filteredlogs[5].MyLogData;
    
    • 如果您的类只包含一个构造函数和一个字段来访问结果,那么使用一个简单的 方法 可能比使用 . 如果你想用一种奇特的方式来做,你可以把它写成一本书 extension method 对于 SpecialArray<MyLog> ,允许您这样访问它:
        List<MyLog> filteredlogs = secialArrayInput.Filter();
        //Example of accessing data
        filteredlogs[5].MyLogData;
    
        4
  •  0
  •   Ricibob    15 年前


    filteredcollection[5].我的日志数据; 等。。