首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有战略与工厂模式的简单问答游戏

具有战略与工厂模式的简单问答游戏
EN

Code Review用户
提问于 2018-12-28 09:07:05
回答 1查看 172关注 0票数 2

我有一个简单的小游戏,用户可以给出简单的答案简单的问题和程序将给出一个结果。拜托,伙计们,做个代码复习,如果有可能的话,回答我的问题放在最下面。

Model类如下所示:

代码语言:javascript
复制
public class Answer
{
    public Answer(int id, int questionId, string content)
    {
        Id = id;
        Content = content;
        QuestionId = questionId;
    }

    public int Id { get; private set; }
    public int QuestionId { get; private set; }
    public string Content { get; private set; }
}
public class Question
{
    public Question(int id, string content, char answer)
    {
        Id = id;
        Content = content;
        Answer = answer;
    }

    public int Id { get; private set; }
    public string Content { get; private set; }
    public char Answer { get; private set; }
}

摘要:

代码语言:javascript
复制
interface IAnswerService
{
    List> GetAnswers();
}
interface IQuestionService
{
    IList GetQuestions();
}
public interface ICalculationService
{
    int CalculatePoints(Dictionary userAnswers);        
}

常数:

代码语言:javascript
复制
public static class Constants
{
    public static class Answers
    {
        public const char A = 'a';
        public const char B = 'b';
        public const char C = 'c';
        public const char D = 'd';
    }
}

Core服务:

代码语言:javascript
复制
static class Factory
{
    public static T CreateInstance() where T : new()
    {
        return new T();
    }
}

服务:

代码语言:javascript
复制
public class AnswerService : IAnswerService
{
    public List> GetAnswers()
    {           
        return new List>() {
            new List() { new Answer(11, 3, "Sequoia"), new Answer(12, 3, 
                "Berch"), new Answer(13, 3, "Lindens"), new Answer(14, 3, "Alder") },
            new List() { new Answer(1, 1, "1"), new Answer(2, 1, "2"), 
                 new Answer(3, 1, "5"), new Answer(4, 1, "6") },
            new List() { new Answer(7, 2, "More than 1"), new Answer(
                8, 2, "More than 2"), new Answer(9, 2, "More than 5"),
                new Answer(10, 2, "More than 6") },                
            new List() { new Answer(15, 4, "yes, I do!"), new 
                Answer(16, 4, "Sure!"), new Answer(17, 4, "Exactly"), new 
                Answer(18, 4, "Yeap!") }
        };
    }
}

CalculationAnswerByAdding服务类别:

代码语言:javascript
复制
class CalculationAnswerByAdding : ICalculationService
{
    public int CalculatePoints(Dictionary userAnswers)
    {
        var sum = 0;
        foreach (var question in userAnswers)
        {
            if (question.Key.Answer == question.Value)
                sum += 1;
        }

        return sum;
    }
}

服务CalculationAnswerBySubtracting

代码语言:javascript
复制
class CalculationAnswerBySubtracting : ICalculationService
{
    public int CalculatePoints(Dictionary userAnswers)
    {
        var sum = 10;
        foreach (var question in userAnswers)
        {
            if (question.Key.Answer == question.Value)
                sum -= 1;
        }

        return sum;
    }
}

public class QuestionService : IQuestionService
{
    public IList GetQuestions()
    {
        return new List() {
            new Question(1, "How many are there contintents?", 
                Constants.Constants.Answers.A),
            new Question(2, "How many are there colours?", Constants.Constants.Answers.B),
            new Question(3, "What is the tallest tree?", Constants.Constants.Answers.C),
            new Question(4, "Do you like dolphins?", Constants.Constants.Answers.D),
        };
    }
}

And Program.cs:

Main()方法Program.cs

代码语言:javascript
复制
static void Main(string[] args)
{
    IQuestionService questionService = Factory.CreateInstance();            
    var questions = questionService.GetQuestions();
        IAnswerService answerService = Factory.CreateInstance();
    var answers = answerService.GetAnswers();

    var questionAnswers = questions.ToDictionary(q => q,
                              q => answers
                                   .SelectMany(a => a)
                                   .Where(b => b.QuestionId == q.Id)
                                   .ToList());
    var userAnswers = new Dictionary();
         GetAsnwers(questionAnswers, userAnswers);

    ICalculationService calculationService = Factory
        .CreateInstance();            
    var userSum = calculationService.CalculatePoints(userAnswers);
    Console.WriteLine(userSum > 3 ? $"Yeah, it is great. Your points are {userSum}." 
        : $"Hey, it is great. Your points are {userSum}");
}

GetAsnwers()方法Program.cs

代码语言:javascript
复制
    private static void GetAsnwers(Dictionary> 
        questionAnswers, Dictionary userAnswers )
    {
        foreach (var questionAnsw in questionAnswers)
        {
            AskQuestion(questionAnsw);
            List allowedAnswers = new List()
            {
                Constants.Constants.Answers.A,
                Constants.Constants.Answers.B,
                Constants.Constants.Answers.C,
                Constants.Constants.Answers.D,
            };

            while (true)
            {
                var userKey = Console.ReadKey().KeyChar;
                Console.WriteLine();
                if (!allowedAnswers.Contains(userKey))
                {
                    AskQuestion(questionAnsw, true);
                }
                else
                {
                    userAnswers.Add(questionAnsw.Key, userKey);
                    break;
                }
            }
        }
    }

AskQuestion()方法Program.cs

代码语言:javascript
复制
private static void AskQuestion(KeyValuePair> questionAnswer, 
    bool showPossibleKeys = false)
{
    if (showPossibleKeys) {
        Console.WriteLine();
        Console.WriteLine("Possible keys are A, B, C or D");
    }

    Console.WriteLine(questionAnswer.Key.Content);
        questionAnswer.Value
            .ForEach(a => Console.WriteLine(a.Content));
 }

伙计们,请看我的密码。我的代码可靠吗?我是否正确地使用策略和工厂模式?如有任何改进和评论,我们将不胜感激。

另外,我的课程组织得好吗?特别是,我把Factory移到CoreServices文件夹中可以吗?还是有更好的方法来组织课程?

EN

回答 1

Code Review用户

回答已采纳

发布于 2018-12-28 18:41:03

我不会问‘我使用模式X正确吗?’,我会问‘模式X为我的问题提供了一个很好的解决方案吗?’要回答这个问题,你需要考虑你的程序的要求。你为什么认为这个计划需要战略、服务和工厂?

模型类

  • 关于你的模型类,为什么要用它们的id来回答问题呢?请注意这如何使调用者的事情变得更麻烦:Main必须做额外的工作来匹配问题的答案。
  • 为什么问题用一个字符来指他们的正确答案?这不仅与ids的使用不一致,而且容易出错,因为这取决于返回答案的顺序。无论如何,这样的标签最好留给UI层。
  • 只读属性不再需要私有设置器了:{ get; }现在已经足够了。

我会选择以下内容(为了简洁起见,我省略了构造函数,而I,因为它们似乎不是必要的):

代码语言:javascript
复制
public class Question
{
    public string Content { get; }
    public IReadOnlyCollection AvailableAnswers { get; }
    public Answer CorrectAnswer { get; }
}

public class Answer
{
    public string Content { get; }
}

请注意,Answer类现在只包含一个字符串,因此您可以删除它,直接将应答字符串的集合存储在Question中,以及正确答案的索引。

服务

  • 为什么把问题和答案分成两个“服务”?问题和答案如果不是总是一起使用的话,所以这种分裂使得事情变得比他们所需要的更困难。它也更容易出错,因为现在您需要保持两个单独的服务保持同步。我会将它们合并到一个问题库中。
  • 这两种计算‘服务’实现的工作或多或少是相同的。我可能会创建某种Result类,它可以用来跟踪用户正确回答和错误回答了多少问题。这将为这些计算算法提供更高层次的概述,并减少代码重复。
  • 我不确定抽象评分机制是否真的有用,但是我不知道你对这个程序的计划是什么,所以我不能说太多。但是,在CalculationAnswerBySubtracting中的硬编码10看起来确实有问题--当然,这应该是可配置的吗?

工厂和常数

  • 这个工厂类没有直接使用new来增加任何价值。如果它的目的是模拟DI容器:通常您要求容器提供“抽象”接口的具体实现,而不是反过来。
  • 这些常量是冗长的,但并没有真正澄清任何事情。Answers.A'A'都是引用答案的同样模糊的方式。给这样的问题贴上标签是一个UI细节,不应该泄露到程序的其他部分。此外,使用这些常量,您可以对每个问题的4个答案进行硬编码,这似乎是一个不必要的限制。
  • AskQuestion不使用这些常量,因为它们的值是小写的,而不是大写的,这可能导致拒绝似乎有效的输入(尝试按shift +A键而不是只按A键)。

其他笔记

  • 就我个人而言,我不喜欢那些ServiceFactory后缀。我会使用像IQuestionRepositoryIScoreCalculator这样的名字--更多的描述性,更少的混乱。
  • foreach (var question in userAnswers)中,question实际上不是一个Question,而是一个键值对,所以这个名称有点误导。无论如何,字典可能不是传递这些信息的最好方法--它不会保留顺序,而且您不需要它的查找功能,您只需要一组问答对。
  • GetAsnwers‘返回’结果通过修改它的一个参数..。为什么它不返回其结果,这也是大多数程序员期望的结果?
  • 在字典中使用Question作为键,而不覆盖EqualsGetHashCode,可能会导致问题。因为现在您没有使用不同(但相同)的Question实例进行任何键查找(实际上根本没有键查找),所以当前的代码工作正常,但这很容易导致将来的问题。
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/210472

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档