【问题标题】:Add a news subscriber using observer pattern with events使用带有事件的观察者模式添加新闻订阅者
【发布时间】:2018-08-30 14:14:46
【问题描述】:

我正在使用观察者模式通过事件在时事通讯中添加和删除订阅者。

我不确定如何处理我正在尝试做的事情。是否可以使用事件添加订阅者以及如何添加?

控制台由带有按钮的表单操作,因此当单击按钮时,它将添加订阅者,当单击删除按钮时,它将删除订阅者,在表单上,​​还有一个发布时事通讯的按钮,该按钮将为每个订阅者发布一份简报。

这是我到目前为止所取得的成果:

class Program
{
    //[STAThread]
    static void Main(string[] args)
    {
        SoftwareRevolution softrev = new Ass_3._1.SoftwareRevolution();
        ConsoleOutput First = new ConsoleOutput(softrev);
        softrev.Datetime = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(true);
        Application.Run(new InputForm());            
    }
}

public delegate void NotifyMe(string Value);

class ConsoleOutput : IEventsObserver
{
    IEventsSubject IEventsSubject;
    public ConsoleOutput(IEventsSubject IEventsSubject)
    {
        this.IEventsSubject = IEventsSubject;
        this.IEventsSubject.Notifier += new Ass_3._1.NotifyMe(UpdateNews);
    }

    public void UpdateNews(string info)
    {

        Console.WriteLine(info);
    }
}

interface IEventsObserver
{
    void UpdateNews(string info);
}

interface IEventsSubject
{
    event NotifyMe Notifier;
}

class SoftwareRevolution : IEventsSubject
{
    List<IEventsObserver> Readers = new List<IEventsObserver>();
    private string datetime;
    public string Datetime
    {
        get
        {
            return datetime;
        }

        set
        {
            datetime = value;
            Notifier(datetime);
        }
    }

    public event NotifyMe Notifier;        
}

【问题讨论】:

  • 发布时事通讯的对象应该有一个在时事通讯发布时触发的事件。然后所有订阅该事件的订阅者都会收到它。
  • @RezaAghaei 谢谢你,但我想做的是通过事件将订阅者添加到订阅者列表中
  • 订阅管理不同于分发时事通讯。发布者只知道发布并引发有关新时事通讯的事件。订阅者管理器帮助订阅者订阅该事件。通常发布者不需要自己保留订阅者列表。 (事件的分发将在没有此类列表的情况下完成。C# 中的事件实现会处理这一点。)

标签: c# winforms events console observer-pattern


【解决方案1】:

发布时事通讯的对象应该有一个在发布时事通讯时触发的事件。然后所有订阅该事件的订阅者都会收到它。

事件的分发将在没有发布者类中的此类列表的情况下完成。事实上,C# 中的委托实现会处理这一点,并且在事件委托后面有一个调用列表。

Publisher 通常不需要保存 Subscriber 对象的列表,如果您需要这样的列表,最好将其保存在 SubscriptionManager。

订阅管理器为订阅者订阅和取消订阅发布者事件。它还可以保存订阅者列表。

示例

Newsletter 类包含一些代表时事通讯的字段:

public class Newsletter
{
    public string Content;
}

NewsLetterPublishedEventArgs 包含有关已发布时事通讯的信息:

public class NewsletterPublishedEventArgs : EventArgs
{
    public Newsletter Newsletter { get; set; }
}

Publisher 类发布时事通讯并在发布后引发事件:

public class Publisher
{
    public event EventHandler<NewsletterPublishedEventArgs> NewsLetterPublished;
    public void PublishNewsLetter()
    {
        var newsLetter = new Newsletter() { Content = $"New publish at {DateTime.Now}" };
        NewsLetterPublished?.Invoke(this, 
            new NewsletterPublishedEventArgs() { Newsletter = newsLetter });
    }
}

Subscriber 类有一个方法允许它接收NewsLetterPublished 通知:

public class Subscriber
{
    public string Name { get; set; }
    public void ReceiveNewsLetter(object sender, NewsletterPublishedEventArgs e)
    {
        MessageBox.Show(e.Newsletter.Content);
    }
}

最后,SubscriptionManager 类订阅和取消订阅发布者的订阅者:

public class SubscriptionManager
{
    public Publisher Publisher => new Publisher();
    private List<Subscriber> subscribers;
    public void Subscribe(Subscriber s)
    {
        if (!subscribers.Contains(s))
        {
            subscribers.Add(s);
            Publisher.NewsLetterPublished += s.ReceiveNewsLetter;
        }
    }
    public void Unsubscribe(Subscriber s)
    {
        if (subscribers.Contains(s))
        {
            subscribers.Remove(s);
            Publisher.NewsLetterPublished -= s.ReceiveNewsLetter;
        }
    }
}

注意

为了简单起见,我创建了一个简单的示例来演示学习目的的逻辑。在现实世界的示例中,您需要使用接口、泛型类和依赖注入。

【讨论】:

  • 非常感谢,在将其解释为我的场景后,它有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多