65.9K
CodeProject 正在变化。 阅读更多。
Home

带好例子解释的责任链设计模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (9投票s)

2015年12月23日

CPOL

4分钟阅读

viewsIcon

22235

在这篇文章中,我想分享我关于责任链设计模式的知识和一个简单的例子。

引言

大家好。我是Acharya,一位热衷于面向对象设计和编程的程序员。几天前,我开始学习设计模式,并尝试用真实世界的例子创建代码样本,以便更容易地记住它们。

在这篇文章中,我想分享我关于责任链设计模式的知识和一个简单的例子。让我们开始吧...

理解模式

责任链是GOF模式中一种强大的行为设计模式,它通过让多个对象有机会处理请求来解耦请求的发送者和接收者。它维护一个接收对象链,并将请求沿着链传递,直到某个对象处理它。

当我第一次读到上述陈述/定义时,我感到有些困惑,并且无法将其与实际实现联系起来。我猜你可能也面临同样的问题。所以,让我们把陈述分解成小块,并将它们与现实世界的例子联系起来。

我们假设有一个小型客户想要组织一些测验比赛,并要求我们为之编写一个应用程序。

他们希望该软件足够通用,以便他们可以动态地为每个事件输入任意数量的问题、参与者及其座位安排。

以下是客户给出的要求列表。

  1. 所有参与者将并排就座。
  2. 参与者数量因活动而异。
  3. 参与者顺序因活动而异。
  4. 我们不确定谁能回答哪个问题。
  5. 测验活动主持人将从第一个人开始问第一个问题。
  6. 如果他回答了,那么他的总分将增加一分,主持人将继续向下一个人提问。
  7. 如果任何参与者未能回答问题,主持人将把问题传给队列/线中的下一个人。
  8. 此过程将一直持续,直到得到答案,或者所有参与者都未能回答该问题。
  9. 测验将一直进行,直到所有问题都完成,而不考虑有多少问题由参与者回答。
  10. 最后,应该为所有参与者宣布结果。

现在,让我们将责任链设计模式的定义与上述例子联系起来。

  • 这里的接收对象是参与者。
  • 请求的发送者是测验活动主持人。
  • 请求是要由参与者回答的问题。
  • 处理请求就是正确回答问题。

由于我们不知道谁拥有回答问题的足够知识,活动主持人将问题传递给一系列参与者,而这个顺序是动态的。每个问题都将按顺序传递,直到得到正确答案,或者所有参与者都未能给出正确答案。如果所有参与者都未能回答一个问题,那么主持人将拿起下一个问题并继续进行。

实现

现在,让我们开始实现。

这里我们有三个关键对象。

  • 提问
  • 参与者
  • 活动主持人

让我们先实现问题和答案的逻辑。在这里,答案被标记为私有字段以提供安全性。它的可见性仅限于Question类和组织者/主持人(将在本文稍后讨论组织者/主持人)。我们有一个指针来指向最初被问到这个问题的原始参与者。CheckAnswer()方法验证参与者给出的答案。

interface IQuestion
{
    string Question1 { get; set; }
    IParticipant Owner { get; set; }
    bool CheckAnswer(string ans);
}

class Question : IQuestion
{
    public string Question1 { get; set; }
    public IParticipant Owner { get; set; }
    private string Answer;

    public Question(string q, string a)
    {
        Question1 = q;
        Answer = a;
    }

    public bool CheckAnswer(string ans)
    {
        return ans.Equals(Answer, StringComparison.InvariantCultureIgnoreCase);
    }
}

现在来到Participants,每个人都有Name、Score属性和一个指向其下一个参与者的指针。

interface IParticipant 
{
    string Name { get; set; }
    int Score { get; set; }
    IParticipant NextParticipent { get; set; }
    void DoAnswer(IQuestion question);
}

class Participant : IParticipant
{
    public IParticipant NextParticipent { get; set; }
    public string Name { get; set; }
    public int Score { get; set; }

    public Participant(IParticipant nextParticipent)
    {
        NextParticipent = nextParticipent;
        Score = 0;
    }

    public void DoAnswer(IQuestion question)
    {
        Console.WriteLine("Hi " + Name + ", Please answer for the question " + question.Question1);
        string ans = Console.ReadLine();

        if (question.CheckAnswer(ans))
        {
            Console.WriteLine("Correct Answer");
            this.Score += 1;
        }
        else if (NextParticipent != question.Owner)
        {
            Console.WriteLine("Wrong Answer. Pass on to next participent.");
            NextParticipent.DoAnswer(question);
        }
        else
        {
            Console.WriteLine("No one answered");
        }
    }
}

如果你查看DoAnswer()方法,你就会理解责任链设计模式中描述的核心逻辑。如果参与者给出的答案是正确的,则将其分数加1并返回。否则,将问题传递给下一个参与者,直到问题被回答,或者下一个指向的参与者是这个问题的最初所有者。

现在是时候实现Event host了。这里活动主持人的职责是协调并根据客户端提供的测验问题和参与者列表来组织测验。

class QuizHost
{
    private List<IQuestion> _questions;
    private List<IParticipant> _participents;

    public QuizHost(List<IQuestion> questions, List<IParticipant> participents)
    {
        _questions = questions;
        _participents = participents;
    }

    public void StartEvent()
    {
        Console.WriteLine("Start of quiz. Welcome All.\n");

        IParticipant currentParticipent = _participents.First();

        foreach (var q in _questions)
        {
            q.Owner = currentParticipent;
            currentParticipent.DoAnswer(q);
            currentParticipent = currentParticipent.NextParticipent;
        }

        Console.WriteLine("\nEnd of quiz. Score card.");
        foreach (var p in _participents)
        {
            Console.WriteLine(p.Name + " : " + p.Score);
        }

        Console.WriteLine("\nThanks for participating.");
    }
}

使用代码

现在,我们的客户,即主组织者,将进来并输入动态输入。

class Program
{
    static void Main(string[] args)
    {
        #region List of Participents

        IParticipant p3 = new Participant(null) { Name = "Raja" };
        IParticipant p2 = new Participant(p3) { Name = "Sree" };
        IParticipant p1 = new Participant(p2) { Name = "Sumesh" };
        p3.NextParticipent = p1;
        List<IParticipant> participents = new List<IParticipant>() { p1, p2, p3 };

        #endregion

        #region List of Questions

        IQuestion q1 = new Question("Is CPU a part of computer?", "Yes");
        IQuestion q2 = new Question("Is IAS a computer course?", "No");
        IQuestion q3 = new Question("Is computer an electronic device?", "Yes");
        List<IQuestion> questions = new List<IQuestion>() { q1, q2, q3 };

        #endregion

        QuizHost myQuiz = new QuizHost(questions, participents);
        myQuiz.StartEvent();

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
}

只需运行此程序,看看它的魔力。你一定会欣赏这个设计模式的美妙之处。

完整源代码供您参考

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        #region List of Participents

        IParticipant p3 = new Participant(null) { Name = "Raja" };
        IParticipant p2 = new Participant(p3) { Name = "Sree" };
        IParticipant p1 = new Participant(p2) { Name = "Sumesh" };
        p3.NextParticipent = p1;
        List<IParticipant> participents = new List<IParticipant>() { p1, p2, p3 };

        #endregion

        #region List of Questions

        IQuestion q1 = new Question("Is CPU a part of computer?", "Yes");
        IQuestion q2 = new Question("Is IAS a computer course?", "No");
        IQuestion q3 = new Question("Is computer an electronic device?", "Yes");
        List<IQuestion> questions = new List<IQuestion>() { q1, q2, q3 };

        #endregion

        QuizHost myQuiz = new QuizHost(questions, participents);
        myQuiz.StartEvent();

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
}

class QuizHost
{
    private List<IQuestion> _questions;
    private List<IParticipant> _participents;

    public QuizHost(List<IQuestion> questions, List<IParticipant> participents)
    {
        _questions = questions;
        _participents = participents;
    }

    public void StartEvent()
    {
        Console.WriteLine("Start of quiz. Welcome All.\n");

        IParticipant currentParticipent = _participents.First();

        foreach (var q in _questions)
        {
            q.Owner = currentParticipent;
            currentParticipent.DoAnswer(q);
            currentParticipent = currentParticipent.NextParticipent;
        }

        Console.WriteLine("\nEnd of quiz. Score card.");
        foreach (var p in _participents)
        {
            Console.WriteLine(p.Name + " : " + p.Score);
        }

        Console.WriteLine("\nThanks for participating.");
    }
}

interface IQuestion
{
    string Question1 { get; set; }
    IParticipant Owner { get; set; }
    bool CheckAnswer(string ans);
}

class Question : IQuestion
{
    public string Question1 { get; set; }
    public IParticipant Owner { get; set; }
    private string Answer;

    public Question(string q, string a)
    {
        Question1 = q;
        Answer = a;
    }

    public bool CheckAnswer(string ans)
    {
        return ans.Equals(Answer, StringComparison.InvariantCultureIgnoreCase);
    }
}

interface IParticipant 
{
    string Name { get; set; }
    int Score { get; set; }
    IParticipant NextParticipent { get; set; }
    void DoAnswer(IQuestion question);
}

class Participant : IParticipant
{
    public IParticipant NextParticipent { get; set; }
    public string Name { get; set; }
    public int Score { get; set; }

    public Participant(IParticipant nextParticipent)
    {
        NextParticipent = nextParticipent;
        Score = 0;
    }

    public void DoAnswer(IQuestion question)
    {
        Console.WriteLine("Hi " + Name + ", Please answer for the question " + question.Question1);
        string ans = Console.ReadLine();

        if (question.CheckAnswer(ans))
        {
            Console.WriteLine("Correct Answer");
            this.Score += 1;
        }
        else if (NextParticipent != question.Owner)
        {
            Console.WriteLine("Wrong Answer. Pass on to next participent.");
            NextParticipent.DoAnswer(question);
        }
        else
        {
            Console.WriteLine("No one answered");
        }
    }
}

历史

  • 初始版本 - 2015年12月23日
© . All rights reserved.