Design Pattern - Observer(C#)
阿新 • • 發佈:2018-11-02
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
Definition
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
Participants
The classes and/or objects participating in this pattern are:
- Subject (Stock)
- Knows its observers. Any number of Observer objects may observe a subject
- Provides an interface for attaching and detaching Observer objects.
- ConcreteSubject (IBM)
- Stores state of interest to ConcreteObserver
- Sends a notification to its observers when its state changes
- Observer (IInvestor)
- Defines an updating interface for objects that should be notified of changes in a subject.
- ConcreteObserver (Investor)
- Maintains a reference to a ConcreteSubject object
- Stores state that should stay consistent with the subject's
- Implements the Observer updating interface to keep its state consistent with the subject's
Sample Code in C#
This structural code demonstrates the Observer pattern in which registered objects are notified of and updated with a state change.
// --------------------------------------------------------------------------------------------------------------------// <copyright company="Chimomo's Company" file="Program.cs">// Respect the work.// </copyright>// <summary>// Structural Observer Design Pattern.// </summary>// --------------------------------------------------------------------------------------------------------------------namespace CSharpLearning{ using System; using System.Collections.Generic; /// <summary> /// Startup class for Structural Observer Design Pattern. /// </summary> internal static class Program { #region Methods /// <summary> /// Entry point into console application. /// </summary> private static void Main() { // Configure Observer pattern var s = new ConcreteSubject(); s.Attach(new ConcreteObserver(s, "X")); s.Attach(new ConcreteObserver(s, "Y")); s.Attach(new ConcreteObserver(s, "Z")); // Change subject and notify observers s.SubjectState = "ABC"; s.Notify(); } #endregion } /// <summary> /// The 'Subject' abstract class /// </summary> internal abstract class Subject { #region Fields /// <summary> /// The observers. /// </summary> private List<Observer> observers = new List<Observer>(); #endregion #region Public Methods and Operators /// <summary> /// The attach. /// </summary> /// <param name="observer"> /// The observer. /// </param> public void Attach(Observer observer) { this.observers.Add(observer); } /// <summary> /// The detach. /// </summary> /// <param name="observer"> /// The observer. /// </param> public void Detach(Observer observer) { this.observers.Remove(observer); } /// <summary> /// The notify. /// </summary> public void Notify() { foreach (Observer o in this.observers) { o.Update(); } } #endregion } /// <summary> /// The 'ConcreteSubject' class /// </summary> internal class ConcreteSubject : Subject { // Gets or sets subject state #region Public Properties /// <summary> /// Gets or sets the subject state. /// </summary> public string SubjectState { get; set; } #endregion } /// <summary> /// The 'Observer' abstract class /// </summary> internal abstract class Observer { #region Public Methods and Operators /// <summary> /// The update. /// </summary> public abstract void Update(); #endregion } /// <summary> /// The 'ConcreteObserver' class /// </summary> internal class ConcreteObserver : Observer { #region Fields /// <summary> /// The name. /// </summary> private string name; /// <summary> /// The observer state. /// </summary> private string observerState; /// <summary> /// The subject. /// </summary> private ConcreteSubject subject; #endregion // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="ConcreteObserver"/> class. /// </summary> /// <param name="subject"> /// The subject. /// </param> /// <param name="name"> /// The name. /// </param> public ConcreteObserver(ConcreteSubject subject, string name) { this.subject = subject; this.name = name; } #endregion #region Public Properties /// <summary> /// Gets or sets the subject. /// </summary> public ConcreteSubject Subject { get { return this.subject; } set { this.subject = value; } } #endregion #region Public Methods and Operators /// <summary> /// The update. /// </summary> public override void Update() { this.observerState = this.subject.SubjectState; Console.WriteLine("Observer {0}'s new state is {1}", this.name, this.observerState); } #endregion }}// Output:/*Observer X's new state is ABCObserver Y's new state is ABCObserver Z's new state is ABC*/
This real-world code demonstrates the Observer pattern in which registered investors are notified every time a stock changes value.
// --------------------------------------------------------------------------------------------------------------------// <copyright company="Chimomo's Company" file="Program.cs">// Respect the work.// </copyright>// <summary>// Real-World Observer Design Pattern.// </summary>// --------------------------------------------------------------------------------------------------------------------namespace CSharpLearning{ using System; using System.Collections.Generic; /// <summary> /// The 'Observer' interface /// </summary> internal interface IInvestor { #region Public Methods and Operators /// <summary> /// The update. /// </summary> /// <param name="stock"> /// The stock. /// </param> void Update(Stock stock); #endregion } /// <summary> /// Startup class for Real-World Observer Design Pattern. /// </summary> internal static class Program { #region Methods /// <summary> /// Entry point into console application. /// </summary> private static void Main() { // Create IBM stock and attach investors var ibm = new IBM("IBM", 120.00); ibm.Attach(new Investor("Sorros")); ibm.Attach(new Investor("Berkshire")); // Fluctuating prices will notify investors ibm.Price = 120.10; ibm.Price = 121.00; ibm.Price = 120.50; ibm.Price = 120.75; } #endregion } /// <summary> /// The 'Subject' abstract class /// </summary> internal abstract class Stock { #region Fields /// <summary> /// The investors. /// </summary> private List<IInvestor> investors = new List<IInvestor>(); /// <summary> /// The price. /// </summary> private double price; #endregion // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="Stock"/> class. /// </summary> /// <param name="symbol"> /// The symbol. /// </param> /// <param name="price"> /// The price. /// </param> protected Stock(string symbol, double price) { this.Symbol = symbol; this.price = price; } #endregion #region Public Properties /// <summary> /// Gets or sets the price. /// </summary> public double Price { get { return this.price; } set { if (this.price != value) { this.price = value; this.Notify(); } } } /// <summary> /// Gets the symbol. /// </summary> public string Symbol { get; private set; } #endregion #region Public Methods and Operators /// <summary> /// The attach. /// </summary> /// <param name="investor"> /// The investor. /// </param> public void Attach(IInvestor investor) { this.investors.Add(investor); } /// <summary> /// The detach. /// </summary> /// <param name="investor"> /// The investor. /// </param> public void Detach(IInvestor investor) { this.investors.Remove(investor); } /// <summary> /// The notify. /// </summary> public void Notify() { foreach (IInvestor investor in this.investors) { investor.Update(this); } Console.WriteLine(string.Empty); } #endregion // Gets or sets the price } /// <summary> /// The 'ConcreteSubject' class /// </summary> internal class IBM : Stock { // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="IBM"/> class. /// </summary> /// <param name="symbol"> /// The symbol. /// </param> /// <param name="price"> /// The price. /// </param> public IBM(string symbol, double price) : base(symbol, price) { } #endregion } /// <summary> /// The 'ConcreteObserver' class /// </summary> internal class Investor : IInvestor { #region Fields /// <summary> /// The name. /// </summary> private string name; #endregion // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="Investor"/> class. /// </summary> /// <param name="name"> /// The name. /// </param> public Investor(string name) { this.name = name; } #endregion // Gets or sets the stock #region Public Properties /// <summary> /// Gets or sets the stock. /// </summary> public Stock Stock { get; set; } #endregion #region Public Methods and Operators /// <summary> /// The update. /// </summary> /// <param name="stock"> /// The stock. /// </param> public void Update(Stock stock) { Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", this.name, stock.Symbol, stock.Price); } #endregion }}// Output:/*Notified Sorros of IBM's change to $120.10Notified Berkshire of IBM's change to $120.10Notified Sorros of IBM's change to $121.00Notified Berkshire of IBM's change to $121.00Notified Sorros of IBM's change to $120.50Notified Berkshire of IBM's change to $120.50Notified Sorros of IBM's change to $120.75Notified Berkshire of IBM's change to $120.75*/