observerblogs.cs

  using System;
  using System.Collections.Generic;
  using System.Collections;
  using System.Threading;
  using System.Windows.Forms;
  using System.Drawing;

  class ObserverPattern {
    
    //Observer Pattern            Judith Bishop Sept 2007
    // Demonstrates Blog updates. Observers can subscribe and unsubscribe
    // online through a GUI.
      
    // State type
    public class Blogs {
      public string Name {get; set;}
      public string Topic {get; set;}
    
      public Blogs (string name, string topic) {
        Name = name;
        Topic = topic;
      }
    }
 
    public delegate void Callback (Blogs blog);
          
    // The Subject runs in a thread and changes its state
    // independently by calling the Iterator. At each change,
    // it notifies its Observers
    // The Callbacks are in a collection based on blogger name
    
    class Subject {
      Dictionary <string,Callback> Notify = new Dictionary <string,Callback> ();
      Simulator simulator = new Simulator();
      const int speed = 4000;
      
      public void Go() {
        new Thread(new ThreadStart(Run)).Start();
      }
    
      void Run () {
        foreach (Blogs blog in simulator) {
          Register(blog.Name); // if necessary
          Notify[blog.Name](blog); // publish changes
          Thread.Sleep(speed); // millisconds
        }
      }
      
      // Adds to the blogger list if unknown
      void Register (string blogger) {
        if (!Notify.ContainsKey(blogger)) {
          Notify[blogger] = delegate {};
        }
      }
    
      public void Attach(string blogger, Callback Update) {
        Register(blogger);
        Notify[blogger] += Update;
      }

      public void Detach(string blogger, Callback Update) {
        // Possible problem here
        Notify[blogger] -= Update;
      }
    }

    class Interact : Form {
      public TextBox wall ;
      public Button subscribeButton, unsubscribeButton ;
      public TextBox messageBox;
      string name;
      
      public Interact(string name, EventHandler Input) {

        Control.CheckForIllegalCrossThreadCalls = true;
        // wall must be first!
        this.name = name;
        wall = new TextBox();
        wall.Multiline = true;
        wall.Location = new Point(0, 30);
        wall.Width = 300;
        wall.Height = 200;
        wall.AcceptsReturn = true;
        wall.Dock = DockStyle.Fill;
        this.Text = name;
              wall.Font = new Font(wall.Font.Name, 12);
        this.Controls.Add(wall);

        // Panel must be second
        Panel p = new Panel();
        messageBox = new TextBox();
        messageBox.Width = 120;
        p.Controls.Add(messageBox);
        subscribeButton = new Button();
        subscribeButton.Left = messageBox.Width;
        subscribeButton.Text = "Subscribe";
        subscribeButton.Click += new EventHandler(Input);
        p.Controls.Add(subscribeButton);
        unsubscribeButton = new Button();
        unsubscribeButton.Left = messageBox.Width+subscribeButton.Width;
        unsubscribeButton.Text = "Unsubscribe";
        unsubscribeButton.Click += new EventHandler(Input);
        p.Controls.Add(unsubscribeButton);

        p.Height = subscribeButton.Height;
        p.Height = unsubscribeButton.Height;
        p.Dock = DockStyle.Top;
        this.Controls.Add(p);
      }

      public void Output(string message) {
        if (this.InvokeRequired)
          this.Invoke((MethodInvoker)delegate() { Output(message); });
        else {
          wall.AppendText(message + "\r\n");
          this.Show();
        }
      }
    }
    
    // Useful if more observer types
    interface IObserver {
      void Update(Blogs state);
    }

    class Observer : IObserver {
      string name;
      Subject blogs;
      Interact visuals;
        
      public Observer (Subject subject, string name) {
              this.blogs = subject;
              this.name = name;
        visuals = new Interact(name,Input);
        new Thread((ParameterizedThreadStart) delegate(object o) {
             Application.Run(visuals);
        }).Start(this);

        // Wait to load the GUI
        while (visuals == null || !visuals.IsHandleCreated) {
            Application.DoEvents();
            Thread.Sleep(100);
        }
        blogs.Attach("Jim",Update);
        blogs.Attach("Eric",Update);
        blogs.Attach("Judith",Update);
      }
    
      public void Input(object source, EventArgs e) {
        // Subscribe to the specified blogger
        if (source == visuals.subscribeButton) {
          blogs.Attach(visuals.messageBox.Text, Update);
          visuals.wall.AppendText("Subscribed to "+visuals.messageBox.Text+"\r\n");
        } else
        //Unsubscribe to the blogger
        if (source == visuals.unsubscribeButton) {
          blogs.Detach(visuals.messageBox.Text, Update);
          visuals.wall.AppendText("Unsubscribed from "+visuals.messageBox.Text+"\r\n");
        }
      }

      public void Update(Blogs blog) {
              visuals.Output("Blog from "+blog.Name+" on "+blog.Topic);
      }
    }

    // Iterator to supply the data
    class Simulator : IEnumerable {
        
      Blogs [] bloggers = {new Blogs ("Jim","UML diagrams"),
      new Blogs("Eric","Iterators"),
      new Blogs("Eric","Extension Methods"),
      new Blogs("Judith","Delegates"),
      new Blogs("Eric","Type inference"),
      new Blogs("Jim","Threads"),
      new Blogs("Eric","Lamda expressions"),
      new Blogs("Judith","Anonymous properties"),
      new Blogs("Eric","Generic delegates"),
      new Blogs("Jim","Efficiency")};

      public IEnumerator GetEnumerator () {
        foreach( Blogs blog in bloggers )
          yield return blog;
        }
      }
    
    static void Main () {
      Subject subject = new Subject();
      Observer Observer =  new Observer(subject,"Thabo");
      Observer observer2 = new Observer(subject,"Ellen");
      subject.Go();
    }
  }
原文地址:https://www.cnblogs.com/shihao/p/2490425.html