没有 IF 条件的多态对象创建 [英] Polymorphic object creation without IF condition

查看:48
本文介绍了没有 IF 条件的多态对象创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的抽象类:

I have an abstract class like this:

public abstract class Records
    {
        public string Type;
        public string Source;
        public int Value;

        protected Records(string type, string source, int value)
        {
            Type = type;
            Source = source;
            Value = value;
        }
}

我想创建许多继承此类的类,并使用来自静态类的值填充它们的 Type 字段,如下所示:

I would like to create many classes inheriting this class, and filling their Type field with a value coming from a static class like this:

public static class ContentTypesString
    {
        public static string DocumentNew { get { return "Document - New this Month"; }}

        public static string HeadlinesNew { get { return "Headlines - New this Month"; }}

       etc...  
    }

我希望能够创建这些子类而无需测试if foo ==document" then type = ContentTypesString.DocumentNew"或等效的 switch case(我真的有一个很多案例)

I would like to be able to create those child classes without having a test "if foo == "document" then type = ContentTypesString.DocumentNew" or an equivalent switch case (I really have a lot of cases)

是否有适合我需求的设计模式?

Is there a design pattern that suits my needs?

正如一些人指出的,我应该展示我如何创建我的实例.

EDIT : As several people pointed out, i should show how i create my instances.

     private delegate SPListItemCollection Query(SPWeb web, DateTime startDate, DateTime endDate);
     private readonly Query _queries;

       #region Constructors

      public QueryHandler(SPWeb web, DateTime startTimeSelectedDate, DateTime endTimeSelectedDate)
          {
            if (web == null) throw new ArgumentNullException("web");

            _web = web;
            _startTimeSelectedDate = startTimeSelectedDate;
            _endTimeSelectedDate = endTimeSelectedDate;
            RecordsList = new List<Records>();

            // Query Invocation List
            _queries = NumberPagePerMonthQuery.PreparedQuery;
            _queries += NumberDocumentsPerMonthQuery.PreparedQuery;
            _queries += NumberHeadlinesPerMonthQuery.PreparedQuery;
            _queries += NumberLeaderboxPerMonthQuery.PreparedQuery;
            _queries += NumberNewsPerMonthQuery.PreparedQuery;
            _queries += NumberPagesModifiedPerMonthQuery.PreparedQuery;
            _queries += NumberPicturesPerMonthQuery.PreparedQuery;
            _queries += NumberTeasingPerMonthQuery.PreparedQuery;
        }

        #endregion Constructors

        #region Public Methods

        // what about NullReferenceException ? C#6 : item?.Foreach(item => {}); ?
        /*** NO C#6 compiler in VS2012... ***/
        public void Queries()
        {
            foreach (var del in _queries.GetInvocationList())
            {
                var queryresult =
                    (SPListItemCollection) del.DynamicInvoke(_web, _startTimeSelectedDate, _endTimeSelectedDate);

                RecordsList.Add(new Records(del.Method.Name, _web.Title, queryresult.Count));
            }
        }

编辑²:我选择的解决方案

  public List<IQuery> QueryList { get; } // no delegate anymore, and static classes became implementations of IQuery interface.

       #region Constructors

      public QueryHandler(SPWeb web, DateTime startTimeSelectedDate, DateTime endTimeSelectedDate)
          {
            if (web == null) throw new ArgumentNullException("web");

            _web = web;
            _startTimeSelectedDate = startTimeSelectedDate;
            _endTimeSelectedDate = endTimeSelectedDate;
            RecordsList = new List<Records>();

            QueryList = new List<IQuery>
            {
                new NumberDocumentsPerMonthQuery(),
                new NumberHeadlinesPerMonthQuery(),
                new NumberLeaderboxPerMonthQuery(),
                new NumberNewsPerMonthQuery(),
                new NumberPagePerMonthQuery(),
                new NumberPagesModifiedPerMonthQuery(),
                new NumberPicturesPerMonthQuery(),
                new NumberTeasingPerMonthQuery()
            };

        }

        #endregion Constructors

        #region Public Methods

        // what about NullReferenceException ? C#6 : item?.Foreach(item => {}); ?
        /*** NO C#6 compiler in VS2012... ***/
          public void Queries()
        {
            foreach (var query in QueryList)
            {
                var queryresult = query.PreparedQuery(_web, _startTimeSelectedDate, _endTimeSelectedDate);
                RecordsList.Add(query.CreateRecord(_web.Title, queryresult.Count));
            }
        }

Record 类遵循@dbraillon 建议的实现IQuery 接口的实现被添加了方法:

Record class follow the implementation suggested by @dbraillon Implementation of IQuery interface were added the method :

public Records CreateRecord(string source, int value)
        {
            return new ModifiedPagesPerMonthRecord(source, value); //or another child of Record class. 
        }

瞧.谢谢大家的帮助.

推荐答案

您想通过对象类型的字符串代码和参数来制作记录集合.

You want to make collection of records, by string code of object type, and parameters.

许多方法之一 - 使用构建器.

One of many way to do it - use builder.

首先我们需要配置构建器:

Firstly we need to configurate builder:

        var builder = new RecordBuilder()
            .RegisterBuilder("document", (source, value) => new Document(source, value))
            .RegisterBuilder("headlines", (source, value) => new Headlines(source, value));

这里我们指定如何使用代码文档"和标题"来构建记录.

here we specify how to build record with code "document" and "headlines".

建立通话记录:

        builder.Build("document", "source", 1);

构建器代码可以这样(这里我们看看我们是否知道如何建立传递类型的记录并制作它):

Builder code can by something like this (here we look if we know how to build record of the passed type and make it):

public class RecordBuilder
{
    public Records Build(string code, string source, int value)
    {
        Func<string, int, Records> buildAction;

        if (recordBuilders.TryGetValue(code, out buildAction))
        {
            return buildAction(source, value);
        }

        return null;
    }

    public RecordBuilder RegisterBuilder(string code, Func<string, int, Records> buildAction)
    {
        recordBuilders.Add(code, buildAction);
        return this;
    }

    private Dictionary<string, Func<string, int, Records>> recordBuilders = new Dictionary<string, Func<string, int, Records>> ();
}


public class Document : Records
{
    public Document(string source, int value) : base(ContentTypesString.DocumentNew, source, value)
    {
    }
}

public class Headlines : Records
{
    public Headlines(string source, int value) : base(ContentTypesString.HeadlinesNew, source, value)
    {
    }
}

这篇关于没有 IF 条件的多态对象创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆