代码之家  ›  专栏  ›  技术社区  ›  Jonathon Reinhart

当只添加新方法而不添加数据时,要使用什么OOP模式?

  •  2
  • Jonathon Reinhart  · 技术社区  · 16 年前

    在我的应用程序中,我处理了几个不同的“参数”,它们来自 IParameter 接口,以及 ParamBase 抽象基类。我现在有两种不同的参数类型,调用它们 FooParameter BarParameter ,两者都源自 . 显然,我可以把他们两个都当作 I参数

    我的问题是具体的 foo参数 s。我现在有几个特定的类,它们都是从 foo参数 ,我们给他们打电话 FP12 , FP13 FP14 等等。这些都有某些特性,这使我在UI中对它们有不同的处理方式(大多数都有与单个位(或位的范围)相关联的名称。请注意,这些特定的派生FP没有与之关联的其他数据,只有属性(以不同方式引用相同数据)或方法。

    Dictionary<String, IParameter> 便于通用访问。问题是,如果我想引用一个具有特殊GUI功能的特定的,我不能写: FP12 fp12 = (FP12)paramList["FP12"] 因为不能向下转换为派生类型(这是理所当然的)。但就我而言,我没有添加任何数据,所以演员阵容理论上是可行的。

    我应该使用什么类型的编程模型?谢谢!

    4 回复  |  直到 16 年前
        1
  •  2
  •   Igor Zevaka    16 年前

    这种方法没有什么真正的错误,除了可能将参数存储在字典中。这样做的目的是什么?尤其是如果你在他们的类名上键入它们。

    List<IParameter> 让控件遍历集合并从中选择正确的子类。

    m_Parameters = new List<IParameter>();
    //This control needs FP12
    foreach(var param in Parameters) {
      var fp12 = param as FP12;
      if (fp12 != null) {
        //do something with the param.
        break;
      }
    }
    

    写了以上这些之后,我想我终于明白了你的意图。如果要执行上可用的操作 FP12 关于的任何子类 FooParameter 那你得停止手术 foo参数 foo参数 ,只有一个 foo参数 (“数据”类)和多个“操作”类。

    //The one implementation of IParameter for all FooParameters
    public class FooParameter : IParameter {
      string Data1 {get;set;}
    }
    
    //base class for Foo Operation, only stores FooParameter 
    public class FooOperationBase {
      protected readonly FooParameter m_Param;
      public FooOperationBase (FooParameter param) {
        m_Param = param;
      } 
    }
    
    //specific operations on FooParameter go in this class
    public class FooOperation12 : FooOperationBase {
      public FooOperation12(FooParameter param) : base(param) {}
    
      public void DoSomeOperation() {
        return m_Param.Data1 + " transformed";
      }
    }
    
        2
  •  1
  •   Matthew Flaschen    16 年前

    paramList["FP12"] 是FP12,那个演员可以。当然,如果不是,它会抛出一个InvalidCastException。你也可以用 as ,如果不确定对象的类型。

    作为 is .

        3
  •  1
  •   Andrew Anderson    16 年前

    我不是100%确定你是从哪里来的这个问题,但你可以这样做:

    class Program
    {
        static void Main(string[] args)
        {
            var paramList = new List<IParameter>();
            paramList.Add(new FooParameter());
            paramList.Add(new BarParameter());
            paramList.Add(new F1());
            paramList.Add(new F2());
    
            foreach (var p in paramList)
            {
                p.DoCommonOperation();
                DoSpecificOperation(p);
            }
    
            Console.ReadKey();
        }
    
        private static void DoSpecificOperation(IParameter p)
        {
            if (p is F1)
            {
                (p as F1).F1Method();
            }
            else if (p is F2)
            {
                (p as F2).F2Method();
            }
    
        }
    
        interface IParameter 
        {
            void DoCommonOperation();
        }
    
        abstract class ParamBase : IParameter
        {
            public virtual void DoCommonOperation()
            {
                Console.WriteLine("ParamBase");
            }
        }
    
        class FooParameter : ParamBase
        {
            public override void DoCommonOperation()
            {
                Console.WriteLine("FooParameter");
            }
        }
    
        class BarParameter : ParamBase
        {
            public override void DoCommonOperation()
            {
                Console.WriteLine("BarParameter");
            }
        }
    
        class F1 : FooParameter
        {
            public override void DoCommonOperation()
            {
                Console.WriteLine("F1");
            }
    
            public void F1Method()
            {
                Console.WriteLine("F1.F1Method");
            }
        }
    
        class F2 : FooParameter
        {
            public override void DoCommonOperation()
            {
                Console.WriteLine("F2");
            }
    
            public void F2Method()
            {
                Console.WriteLine("F2.F2Method");
            }
        }
    }
    

    实际上,类中有一个方法控制IParameter对象的列表,该对象知道如何调用特定的实现,并使用is/as来实现。

        4
  •  1
  •   code4life    16 年前

    为了理智起见,为什么不使用 Dictionary<Type, IParameter> ? 通过一些泛型,您可以做到:

    public interface IParameter { }
    public class FP12 : IParameter { public string fieldFP12 { get; set; } }
    public class FP11 : IParameter { public string fieldFP11 { get; set; } }
    
    public static class DictionaryHelper
    {
        public static T GetParameter<T>(this Dictionary<System.Type, 
          IParameter> target) where T : IParameter
        {
            return (T)target[typeof(T)];
        }
    }
    

    示例程序和输出:

    class Program
    {
        static void Main()
        {
            Dictionary<Type, IParameter> parameters = 
              new Dictionary<Type, IParameter>();
            parameters.Add(typeof(FP12), new FP12 { fieldFP12 = "This is FP12" });
            parameters.Add(typeof(FP11), new FP11 { fieldFP11 = "This is FP11"});
    
            // THIS IS WHERE YOU GET THE IPARAMETER YOU WANT - THE GENERICS WAY...
            var fp12 = parameters.GetParameter<FP12>();
            var fp11 = parameters.GetParameter<FP11>();
    
            Console.WriteLine(fp12.fieldFP12);
            Console.WriteLine(fp11.fieldFP11);
            Console.ReadLine();
        }
    }
    

    结果输出:

    This is FP12
    This is FP11