├── .github └── FUNDING.yml ├── bin └── Debug │ ├── ObserverPattern.exe │ ├── ObserverPattern.pdb │ ├── ObserverPattern.vshost.exe │ ├── Microsoft.VisualBasic.PowerPacks.Vs.dll │ └── ObserverPattern.vshost.exe.manifest ├── obj └── x86 │ └── Debug │ ├── ObserverPattern.exe │ ├── ObserverPattern.pdb │ ├── ObserverPattern.MainForm.resources │ ├── ObserverPattern.BallObserver.resources │ ├── DesignTimeResolveAssemblyReferences.cache │ ├── ObserverPattern.MovingBallObserver.resources │ ├── ObserverPattern.csproj.GenerateResource.Cache │ ├── DesignTimeResolveAssemblyReferencesInput.cache │ ├── ObserverPattern.Properties.Resources.resources │ ├── ObserverPattern.csprojResolveAssemblyReference.cache │ ├── ObserverPattern.ObserverPattern.Observer.SimpleObserver.resources │ └── ObserverPattern.csproj.FileListAbsolute.txt ├── Properties ├── Settings.settings ├── Settings.Designer.cs ├── AssemblyInfo.cs ├── Resources.Designer.cs └── Resources.resx ├── ObserverPattern ├── Observer │ ├── IObserver.cs │ ├── SimpleObserver.cs │ ├── BallObserver.cs │ ├── SimpleObserver.Designer.cs │ ├── MovingBallObserver.cs │ ├── MovingBallObserver.Designer.cs │ ├── BallObserver.Designer.cs │ ├── BallObserver.resx │ ├── SimpleObserver.resx │ └── MovingBallObserver.resx └── Subject │ ├── ISubject.cs │ └── ColorSubject.cs ├── Program.cs ├── Others ├── CircleShape.cs └── ColorComboBox.cs ├── MainForm.cs ├── MainForm.Designer.cs ├── ObserverPattern.csproj ├── README.md └── MainForm.resx /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [zied-snoussi] 4 | -------------------------------------------------------------------------------- /bin/Debug/ObserverPattern.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/bin/Debug/ObserverPattern.exe -------------------------------------------------------------------------------- /bin/Debug/ObserverPattern.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/bin/Debug/ObserverPattern.pdb -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.exe -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.pdb -------------------------------------------------------------------------------- /bin/Debug/ObserverPattern.vshost.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/bin/Debug/ObserverPattern.vshost.exe -------------------------------------------------------------------------------- /bin/Debug/Microsoft.VisualBasic.PowerPacks.Vs.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/bin/Debug/Microsoft.VisualBasic.PowerPacks.Vs.dll -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.MainForm.resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.MainForm.resources -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.BallObserver.resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.BallObserver.resources -------------------------------------------------------------------------------- /obj/x86/Debug/DesignTimeResolveAssemblyReferences.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/DesignTimeResolveAssemblyReferences.cache -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.MovingBallObserver.resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.MovingBallObserver.resources -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.csproj.GenerateResource.Cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.csproj.GenerateResource.Cache -------------------------------------------------------------------------------- /obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.Properties.Resources.resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.Properties.Resources.resources -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.csprojResolveAssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.csprojResolveAssemblyReference.cache -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.ObserverPattern.Observer.SimpleObserver.resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zied-snoussi/ObserverPattern/HEAD/obj/x86/Debug/ObserverPattern.ObserverPattern.Observer.SimpleObserver.resources -------------------------------------------------------------------------------- /Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/IObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | namespace ObserverPattern 8 | { 9 | public interface IObserver 10 | { 11 | void ColorChanged(Color newColor); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ObserverPattern/Subject/ISubject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace ObserverPattern 7 | { 8 | public interface ISubject 9 | { 10 | void Register(IObserver observer); 11 | void Unregister(IObserver observer); 12 | 13 | void Notify(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bin/Debug/ObserverPattern.vshost.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | namespace ObserverPattern 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// The main entry point for the application. 12 | /// 13 | [STAThread] 14 | static void Main() 15 | { 16 | Application.EnableVisualStyles(); 17 | Application.SetCompatibleTextRenderingDefault(false); 18 | Control.CheckForIllegalCrossThreadCalls = false; 19 | Application.Run(new MainForm()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/SimpleObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace ObserverPattern.ObserverPattern.Observer 11 | { 12 | public partial class SimpleObserver : Form, IObserver 13 | { 14 | public SimpleObserver() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | #region IObserver Members 20 | 21 | public void ColorChanged(Color newColor) 22 | { 23 | this.BackColor = newColor; 24 | } 25 | 26 | #endregion 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/BallObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace ObserverPattern 11 | { 12 | public partial class BallObserver : Form, IObserver 13 | { 14 | public BallObserver() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | #region IObserver Members 20 | 21 | public void ColorChanged(Color newColor) 22 | { 23 | circleShape1.FillColor = newColor; 24 | circleShape2.FillColor = newColor; 25 | circleShape3.FillColor = newColor; 26 | } 27 | 28 | #endregion 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Others/CircleShape.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | using System.Drawing; 7 | 8 | namespace ObserverPattern.Others 9 | { 10 | public class CircleShape : Control 11 | { 12 | private Color _FillColor = Color.Blue; 13 | private SolidBrush _brush; 14 | 15 | public CircleShape() 16 | { 17 | _brush = new SolidBrush(_FillColor); 18 | } 19 | 20 | public Color FillColor 21 | { 22 | get { return _FillColor; } 23 | set 24 | { 25 | _FillColor = value; 26 | _brush.Color = value; 27 | 28 | this.Invalidate(); 29 | } 30 | } 31 | 32 | protected override void OnPaint(PaintEventArgs e) 33 | { 34 | e.Graphics.FillEllipse(_brush, 0, 0, this.Width - 1, this.Height - 1); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ObserverPattern/Subject/ColorSubject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | namespace ObserverPattern.ObserverPattern.Subject 8 | { 9 | public class ColorSubject : ISubject 10 | { 11 | private Color _Color = Color.Blue; 12 | 13 | public Color Color 14 | { 15 | get { return _Color; } 16 | set 17 | { 18 | _Color = value; 19 | Notify(); 20 | } 21 | } 22 | 23 | #region ISubject Members 24 | 25 | private HashSet _observers = new HashSet(); 26 | 27 | public void Register(IObserver observer) 28 | { 29 | _observers.Add(observer); 30 | } 31 | 32 | public void Unregister(IObserver observer) 33 | { 34 | _observers.Remove(observer); 35 | } 36 | 37 | public void Notify() 38 | { 39 | _observers.ToList().ForEach(o => o.ColorChanged(Color)); 40 | } 41 | 42 | #endregion 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.225 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ObserverPattern.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ObserverPattern")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ObserverPattern")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f2de286b-7337-4fd0-8d39-6d631433c7c7")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/SimpleObserver.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern.ObserverPattern.Observer 2 | { 3 | partial class SimpleObserver 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // SimpleObserver 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.ClientSize = new System.Drawing.Size(263, 167); 38 | this.Name = "SimpleObserver"; 39 | this.Text = "Simple Observer"; 40 | this.ResumeLayout(false); 41 | 42 | } 43 | 44 | #endregion 45 | } 46 | } -------------------------------------------------------------------------------- /obj/x86/Debug/ObserverPattern.csproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\bin\Debug\ObserverPattern.exe 2 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\bin\Debug\ObserverPattern.pdb 3 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\bin\Debug\Microsoft.VisualBasic.PowerPacks.Vs.dll 4 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\bin\Debug\Microsoft.VisualBasic.PowerPacks.Vs.xml 5 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.csprojResolveAssemblyReference.cache 6 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.BallObserver.resources 7 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.MainForm.resources 8 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.MovingBallObserver.resources 9 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.ObserverPattern.Observer.SimpleObserver.resources 10 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.Properties.Resources.resources 11 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.csproj.GenerateResource.Cache 12 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.exe 13 | E:\Game Engine Programming\ObserverPattern\ObserverPattern\ObserverPattern\obj\x86\Debug\ObserverPattern.pdb 14 | -------------------------------------------------------------------------------- /MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using ObserverPattern.ObserverPattern.Subject; 10 | using ObserverPattern.ObserverPattern.Observer; 11 | 12 | namespace ObserverPattern 13 | { 14 | public partial class MainForm : Form 15 | { 16 | private ColorSubject _subject = new ColorSubject(); 17 | 18 | public MainForm() 19 | { 20 | InitializeComponent(); 21 | 22 | // Initialize 23 | nextLeft = 0; 24 | ColorCombo.SelectedColor = _subject.Color; 25 | Application.DoEvents(); 26 | Add3ObserverForms(); 27 | } 28 | 29 | private int nextTop = 0; 30 | private int nextLeft = 0; 31 | 32 | private void Add3ObserverForms() 33 | { 34 | for (int i = 1; i <= 5; i++) 35 | { 36 | SetCommonProperties(new BallObserver()); 37 | SetCommonProperties(new SimpleObserver()); 38 | SetCommonProperties(new MovingBallObserver()); 39 | nextLeft += 300; 40 | nextTop = 0; 41 | } 42 | } 43 | 44 | private void SetCommonProperties(Form form) 45 | { 46 | form.Left = nextLeft; 47 | form.Top = nextTop; 48 | form.StartPosition = FormStartPosition.Manual; 49 | (form as IObserver).ColorChanged(_subject.Color); 50 | form.Show(); 51 | 52 | _subject.Register(form as IObserver); 53 | 54 | nextTop += form.Height; 55 | } 56 | 57 | private void ColorCombo_SelectedIndexChanged(object sender, EventArgs e) 58 | { 59 | _subject.Color = ColorCombo.SelectedColor; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/MovingBallObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using System.Threading; 10 | 11 | namespace ObserverPattern 12 | { 13 | public partial class MovingBallObserver : Form, IObserver 14 | { 15 | public MovingBallObserver() 16 | { 17 | InitializeComponent(); 18 | 19 | Application.DoEvents(); 20 | StartThread(); 21 | } 22 | 23 | private void StartThread() 24 | { 25 | circleShape1.Left = new Random().Next(this.Width - 100); 26 | circleShape1.Top = new Random().Next(this.Height - 100); 27 | 28 | ThreadStart threadStart = new ThreadStart(MoveBall); 29 | Thread thread = new Thread(threadStart); 30 | thread.Start(); 31 | } 32 | 33 | #region IObserver Members 34 | 35 | public void ColorChanged(Color newColor) 36 | { 37 | circleShape1.FillColor = newColor; 38 | } 39 | 40 | #endregion 41 | 42 | private int _changeX = 5, _changeY = 5; 43 | 44 | public void MoveBall() 45 | { 46 | Thread.Sleep(500); 47 | Application.DoEvents(); 48 | 49 | while (true) 50 | { 51 | try 52 | { 53 | circleShape1.Left += _changeX; 54 | circleShape1.Top += _changeY; 55 | }catch{} 56 | 57 | if ((circleShape1.Left + circleShape1.Width > this.Width - 15) 58 | || 59 | (circleShape1.Left < 0)) 60 | _changeX = _changeX * (-1); 61 | 62 | if ((circleShape1.Top + circleShape1.Height > this.Height - circleShape1.Height) 63 | || 64 | (circleShape1.Top < 0)) 65 | _changeY = _changeY * (-1); 66 | 67 | Thread.Sleep(50); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/MovingBallObserver.Designer.cs: -------------------------------------------------------------------------------- 1 | using ObserverPattern.Others; 2 | namespace ObserverPattern 3 | { 4 | partial class MovingBallObserver 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.circleShape1 = new CircleShape(); 33 | this.SuspendLayout(); 34 | // 35 | // circleShape1 36 | // 37 | this.circleShape1.FillColor = System.Drawing.Color.Blue; 38 | this.circleShape1.Location = new System.Drawing.Point(48, 91); 39 | this.circleShape1.Name = "circleShape1"; 40 | this.circleShape1.Size = new System.Drawing.Size(49, 41); 41 | this.circleShape1.TabIndex = 0; 42 | this.circleShape1.Text = "circleShape1"; 43 | // 44 | // MovingBallObserver 45 | // 46 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 47 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 48 | this.BackColor = System.Drawing.Color.White; 49 | this.ClientSize = new System.Drawing.Size(276, 193); 50 | this.Controls.Add(this.circleShape1); 51 | this.Name = "MovingBallObserver"; 52 | this.Text = "Moving Ball Observer"; 53 | this.ResumeLayout(false); 54 | 55 | } 56 | 57 | #endregion 58 | 59 | private Others.CircleShape circleShape1; 60 | 61 | } 62 | } -------------------------------------------------------------------------------- /Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.225 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ObserverPattern.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ObserverPattern.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/BallObserver.Designer.cs: -------------------------------------------------------------------------------- 1 | using ObserverPattern.Others; 2 | namespace ObserverPattern 3 | { 4 | partial class BallObserver 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.circleShape1 = new CircleShape(); 33 | this.circleShape2 = new CircleShape(); 34 | this.circleShape3 = new CircleShape(); 35 | this.SuspendLayout(); 36 | // 37 | // circleShape1 38 | // 39 | this.circleShape1.Location = new System.Drawing.Point(12, 12); 40 | this.circleShape1.Name = "circleShape1"; 41 | this.circleShape1.Size = new System.Drawing.Size(42, 38); 42 | this.circleShape1.TabIndex = 0; 43 | this.circleShape1.Text = "circleShape1"; 44 | // 45 | // circleShape2 46 | // 47 | this.circleShape2.Location = new System.Drawing.Point(170, 23); 48 | this.circleShape2.Name = "circleShape2"; 49 | this.circleShape2.Size = new System.Drawing.Size(94, 89); 50 | this.circleShape2.TabIndex = 1; 51 | this.circleShape2.Text = "circleShape2"; 52 | // 53 | // circleShape3 54 | // 55 | this.circleShape3.Location = new System.Drawing.Point(68, 116); 56 | this.circleShape3.Name = "circleShape3"; 57 | this.circleShape3.Size = new System.Drawing.Size(57, 48); 58 | this.circleShape3.TabIndex = 2; 59 | this.circleShape3.Text = "circleShape3"; 60 | // 61 | // BallObserver 62 | // 63 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 64 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 65 | this.BackColor = System.Drawing.Color.White; 66 | this.ClientSize = new System.Drawing.Size(276, 193); 67 | this.Controls.Add(this.circleShape3); 68 | this.Controls.Add(this.circleShape2); 69 | this.Controls.Add(this.circleShape1); 70 | this.Name = "BallObserver"; 71 | this.Text = "Ball Observer"; 72 | this.ResumeLayout(false); 73 | 74 | } 75 | 76 | #endregion 77 | 78 | private Others.CircleShape circleShape1; 79 | private Others.CircleShape circleShape2; 80 | private Others.CircleShape circleShape3; 81 | 82 | } 83 | } -------------------------------------------------------------------------------- /MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | using ObserverPattern.Others; 2 | namespace ObserverPattern 3 | { 4 | partial class MainForm 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); 33 | this.label1 = new System.Windows.Forms.Label(); 34 | this.ColorCombo = new ColorComboBoxApp.ColorComboBox(); 35 | this.SuspendLayout(); 36 | // 37 | // label1 38 | // 39 | this.label1.AutoSize = true; 40 | this.label1.Location = new System.Drawing.Point(25, 53); 41 | this.label1.Name = "label1"; 42 | this.label1.Size = new System.Drawing.Size(71, 13); 43 | this.label1.TabIndex = 2; 44 | this.label1.Text = "Change Color"; 45 | // 46 | // ColorCombo 47 | // 48 | this.ColorCombo.DataSource = ((object)(resources.GetObject("ColorCombo.DataSource"))); 49 | this.ColorCombo.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; 50 | this.ColorCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 51 | this.ColorCombo.FormattingEnabled = true; 52 | this.ColorCombo.Location = new System.Drawing.Point(28, 69); 53 | this.ColorCombo.Name = "ColorCombo"; 54 | this.ColorCombo.SelectedColor = System.Drawing.Color.WhiteSmoke; 55 | this.ColorCombo.Size = new System.Drawing.Size(166, 21); 56 | this.ColorCombo.TabIndex = 3; 57 | this.ColorCombo.SelectedIndexChanged += new System.EventHandler(this.ColorCombo_SelectedIndexChanged); 58 | // 59 | // MainForm 60 | // 61 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 62 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 63 | this.BackColor = System.Drawing.Color.WhiteSmoke; 64 | this.ClientSize = new System.Drawing.Size(222, 172); 65 | this.Controls.Add(this.ColorCombo); 66 | this.Controls.Add(this.label1); 67 | this.Name = "MainForm"; 68 | this.Text = "Observer Pattern"; 69 | this.ResumeLayout(false); 70 | this.PerformLayout(); 71 | 72 | } 73 | 74 | #endregion 75 | 76 | private System.Windows.Forms.Label label1; 77 | private ColorComboBoxApp.ColorComboBox ColorCombo; 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /Others/ColorComboBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | using System.Drawing; 7 | using System.Reflection; 8 | using System.Collections; 9 | 10 | namespace ColorComboBoxApp 11 | { 12 | /// 13 | /// Inherits from existing ComboBox 14 | /// 15 | public class ColorComboBox : ComboBox 16 | { 17 | public ColorComboBox() 18 | { 19 | FillColors(); 20 | 21 | // Change DrawMode for custom drawing 22 | this.DrawMode = DrawMode.OwnerDrawFixed; 23 | this.DropDownStyle = ComboBoxStyle.DropDownList; 24 | } 25 | 26 | private void FillColors() 27 | { 28 | if (!DesignMode) 29 | { 30 | this.Items.Clear(); 31 | var items = typeof(Color).GetProperties(BindingFlags.Static | BindingFlags.Public).Where(c => c.PropertyType == typeof(Color)).Select(c => (Color)c.GetValue(c, null)).ToList(); 32 | foreach (Color color in items) 33 | this.Items.Add(color); 34 | } 35 | } 36 | 37 | /// 38 | /// Override Draw Method 39 | /// 40 | /// 41 | protected override void OnDrawItem(DrawItemEventArgs e) 42 | { 43 | if (e.Index >= 0) 44 | { 45 | Color color = (Color)(this.DataSource as IList)[e.Index]; 46 | 47 | int nextX = 0; 48 | 49 | e.Graphics.FillRectangle(new SolidBrush(e.BackColor), e.Bounds); 50 | DrawColor(e, color, ref nextX); 51 | DrawText(e, color, nextX); 52 | } 53 | else 54 | base.OnDrawItem(e); 55 | } 56 | 57 | /// 58 | /// Draw the Color rectangle filled with item color 59 | /// 60 | /// 61 | /// 62 | /// 63 | private void DrawColor(DrawItemEventArgs e, Color color, ref int nextX) 64 | { 65 | int width = e.Bounds.Height * 2 - 8; 66 | Rectangle rectangle = new Rectangle(e.Bounds.X + 3, e.Bounds.Y + 3, width, e.Bounds.Height - 6); 67 | e.Graphics.FillRectangle(new SolidBrush(color), rectangle); 68 | 69 | nextX = width + 8; 70 | } 71 | 72 | /// 73 | /// Draw the color name next to the color rectangle 74 | /// 75 | /// 76 | /// 77 | /// 78 | private void DrawText(DrawItemEventArgs e, Color color, int nextX) 79 | { 80 | e.Graphics.DrawString(color.Name, e.Font, new SolidBrush(e.ForeColor), new PointF(nextX, e.Bounds.Y + (e.Bounds.Height - e.Font.Height) / 2)); 81 | } 82 | 83 | /// 84 | /// Gets/sets the selected color of ComboBox 85 | /// (Default color is Black) 86 | /// 87 | public Color SelectedColor 88 | { 89 | get 90 | { 91 | if (this.SelectedItem != null) 92 | return (Color)this.SelectedItem; 93 | 94 | return Color.Black; 95 | } 96 | set 97 | { 98 | int ix = (this.DataSource as IList).IndexOf(value); 99 | if (ix >= 0) 100 | this.SelectedIndex = ix; 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /ObserverPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {F90988AE-FF29-43E4-920E-BB678A2A7BC4} 9 | WinExe 10 | Properties 11 | ObserverPattern 12 | ObserverPattern 13 | v4.0 14 | Client 15 | 512 16 | 17 | 18 | x86 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | x86 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | Form 53 | 54 | 55 | BallObserver.cs 56 | 57 | 58 | Form 59 | 60 | 61 | MovingBallObserver.cs 62 | 63 | 64 | Form 65 | 66 | 67 | SimpleObserver.cs 68 | 69 | 70 | 71 | 72 | 73 | Form 74 | 75 | 76 | MainForm.cs 77 | 78 | 79 | Component 80 | 81 | 82 | Component 83 | 84 | 85 | 86 | 87 | BallObserver.cs 88 | 89 | 90 | MainForm.cs 91 | 92 | 93 | MovingBallObserver.cs 94 | 95 | 96 | SimpleObserver.cs 97 | 98 | 99 | ResXFileCodeGenerator 100 | Resources.Designer.cs 101 | Designer 102 | 103 | 104 | True 105 | Resources.resx 106 | 107 | 108 | SettingsSingleFileGenerator 109 | Settings.Designer.cs 110 | 111 | 112 | True 113 | Settings.settings 114 | True 115 | 116 | 117 | 118 | 125 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/BallObserver.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/SimpleObserver.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /ObserverPattern/Observer/MovingBallObserver.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Real-time Market Data Tracker 2 | 3 | ## :speech_balloon: Intent 4 | ***Real-time Market Data Tracker*** is a sophisticated financial analysis and monitoring system that leverages the Observer design pattern to deliver real-time market data updates to traders, investors, and financial analysts. It is designed to provide a competitive edge in the dynamic world of finance. 5 | 6 | ![Real-time Market Data Tracker](https://user-images.githubusercontent.com/74665047/210447316-e1817262-9fe2-435d-b9b5-4f13126f95fe.png) 7 | 8 | ## :frowning_face: Problem 9 | In the realm of financial markets, the ability to access and respond to real-time market data is paramount. Traders and investors require accurate, timely information to make informed decisions. Conventional methods of monitoring market data, such as manual tracking or email alerts, fall short in delivering the speed and precision demanded by the financial industry. 10 | 11 | ![Problem](https://user-images.githubusercontent.com/74665047/210435947-9bf4e2d7-9b31-4bdb-a57a-66b75464cc1c.png) 12 | 13 | ## :blush: Solution 14 | The **Real-time Market Data Tracker** relies on the Observer pattern to provide immediate updates on market data. In this pattern, market data serves as the publisher, while analysis modules, user dashboards, and alert systems act as subscribers. This architecture ensures that users receive instant notifications and updates on market changes, enabling them to stay ahead of the curve. 15 | 16 | ![Solution](https://user-images.githubusercontent.com/74665047/210436135-e271266d-7902-4bad-9315-b1494f5ecbde.png) 17 | 18 | ## :car: Real-World 19 | ![Real-World](https://user-images.githubusercontent.com/74665047/210436320-e07628f6-875c-4b7f-bf47-fe24bcd93731.png) 20 | 21 | The Observer pattern finds practical use in the financial industry. Just as subscribers receive magazines directly in their mailboxes after subscribing, financial professionals benefit from real-time market data updates delivered to their devices. Subscribers can easily opt in or out of specific updates, allowing for a tailored experience. 22 | 23 | ## :trident: Structure 24 | ![Structure](https://user-images.githubusercontent.com/74665047/210439969-e38ca98d-c5c5-4c51-b10e-b4b3b0d10e96.png) 25 | 26 | 1. **Market Data Publisher**: Responsible for issuing events when market data changes. It maintains a subscription infrastructure to manage subscribers. 27 | 28 | 2. **Subscriber Interface**: Declares the notification interface, often consisting of a single update method. All subscribers implement this interface. 29 | 30 | 3. **Concrete Subscribers**: Respond to notifications issued by the market data publisher. Each subscriber class must implement the subscriber interface. 31 | 32 | 4. **Client**: Creates publisher and subscriber objects separately and registers subscribers for market data updates. 33 | 34 | ## :diamond_shape_with_a_dot_inside: Pseudocode 35 | In this example, the Observer pattern allows the market data publisher to notify various analysis modules and user dashboards about changes in market data. 36 | 37 | ![Pseudocode](https://user-images.githubusercontent.com/74665047/210440406-00a45146-aadf-48b5-84dc-7bd602ad4b5e.png) 38 | 39 | The subscription list is dynamic, enabling objects to join or leave the list as needed, ensuring flexibility and scalability. 40 | 41 | ```python 42 | # Market data publisher class includes subscription management code and notification methods. 43 | class MarketDataPublisher: 44 | private field subscribers: hash map of event types and listeners 45 | 46 | method subscribe(eventType, listener) is 47 | subscribers.add(eventType, listener) 48 | 49 | method unsubscribe(eventType, listener) is 50 | subscribers.remove(eventType, listener) 51 | 52 | method notify(eventType, data) is 53 | foreach (listener in subscribers.of(eventType)) do 54 | listener.update(data) 55 | 56 | # Concrete market data publisher contains real business logic of tracking market data changes. 57 | class RealTimeMarketDataPublisher: 58 | public field events: MarketDataPublisher 59 | private field marketData: MarketData 60 | 61 | constructor RealTimeMarketDataPublisher() is 62 | events = new MarketDataPublisher() 63 | 64 | method trackMarketData() is 65 | # Logic for tracking market data changes 66 | # ... 67 | 68 | # Subscriber interface declares the notification interface. 69 | interface MarketDataSubscriber: 70 | method update(data) 71 | 72 | # Concrete subscribers respond to market data updates. 73 | class AnalysisModule implements MarketDataSubscriber is 74 | private field analysisData: AnalysisData 75 | 76 | method update(data) is 77 | analysisData.process(data) 78 | 79 | class UserDashboard implements MarketDataSubscriber is 80 | private field user: User 81 | 82 | method update(data) is 83 | user.displayData(data) 84 | 85 | # Client configures publishers and registers subscribers for market data updates. 86 | class FinancialApplication is 87 | method configure() is 88 | marketDataPublisher = new RealTimeMarketDataPublisher() 89 | 90 | analysisModule = new AnalysisModule() 91 | marketDataPublisher.events.subscribe("marketChange", analysisModule) 92 | 93 | userDashboard = new UserDashboard() 94 | marketDataPublisher.events.subscribe("marketChange", userDashboard) 95 | ``` 96 | 97 | ## :bulb: Applicability 98 | ### Use the Observer pattern when changes to the state of one object must trigger changes in other objects, and the set 99 | 100 | of objects is not known in advance or changes dynamically. 101 | 102 | This pattern is highly suitable for graphical user interfaces. For example, when creating custom button classes, you can enable clients to attach custom code to buttons, allowing them to respond to button clicks dynamically. 103 | 104 | ### Use the pattern when some objects need to observe others, but only for a limited time or in specific cases. 105 | 106 | The subscription list is dynamic, allowing subscribers to join or leave as needed. 107 | 108 | ## :keyboard: How to Implement 109 | 110 | 1. Analyze your application's business logic to separate the core functionality (the publisher) from other code that will become subscriber classes. 111 | 112 | 2. Declare the subscriber interface, which should include at least a single update method. 113 | 114 | 3. Define the publisher interface with methods for adding and removing subscriber objects from the list. Ensure that publishers interact with subscribers solely through this interface. 115 | 116 | 4. Decide where to place the subscription list and the implementation of subscription methods. Often, this code remains consistent for various publishers, making it suitable for an abstract class derived directly from the publisher interface. Concrete publishers can extend this class to inherit the subscription behavior. 117 | 118 | 5. If applying the pattern to an existing class hierarchy, consider a composition-based approach. Create a separate object responsible for subscription logic and have all publishers use it. 119 | 120 | 6. Develop concrete publisher classes. Whenever a significant event occurs within a publisher, notify all subscribers. 121 | 122 | 7. Implement update notification methods in concrete subscriber classes. Most subscribers will require contextual information about the event, which can be passed as arguments to the notification method. Alternatively, the publisher can pass itself to allow subscribers to fetch necessary data directly. 123 | 124 | 8. The client should create all required subscribers and register them for publisher updates. 125 | 126 | ## :balance_scale: Pros and Cons 127 | 128 | :heavy_check_mark: Open/Closed Principle: You can introduce new subscriber classes without modifying the publisher's code (and vice versa if a publisher interface exists). 129 | 130 | :heavy_check_mark: Dynamic Relationships: Subscribers can join or leave the list as needed. 131 | 132 | :x: Random Notification Order: Subscribers are notified in a random order. 133 | 134 | ## :arrows_counterclockwise: Relations with Other Patterns 135 | 136 | - Chain of Responsibility, Command, Mediator, and Observer all address various methods of connecting senders and receivers of requests: 137 | 138 | - Chain of Responsibility passes a request sequentially along a dynamic chain of potential receivers until one handles it. 139 | 140 | - Command establishes unidirectional connections between senders and receivers. 141 | 142 | - Mediator eliminates direct connections between senders and receivers, forcing communication through a mediator object. 143 | 144 | - Observer enables receivers to dynamically subscribe to and unsubscribe from receiving requests. 145 | 146 | - The distinction between Mediator and Observer can sometimes be blurred. In many cases, you can implement either pattern or even both simultaneously. The primary goal of Mediator is to eliminate mutual dependencies among system components, while Observer allows one-way connections between objects. A popular implementation of Mediator uses Observer, where the mediator acts as the publisher, and components are subscribers. In this configuration, Mediator resembles Observer. 147 | 148 | When in doubt, remember that you can implement Mediator in different ways. For instance, you can permanently link all components to the same mediator object. While this implementation doesn't resemble Observer, it remains a form of the Mediator pattern. 149 | -------------------------------------------------------------------------------- /MainForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0 123 | dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EEAQAAAIwBU3lzdGVtLkNv 124 | bGxlY3Rpb25zLkdlbmVyaWMuTGlzdGAxW1tTeXN0ZW0uRHJhd2luZy5Db2xvciwgU3lzdGVtLkRyYXdp 125 | bmcsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iMDNmNWY3 126 | ZjExZDUwYTNhXV0DAAAABl9pdGVtcwVfc2l6ZQhfdmVyc2lvbgQAABZTeXN0ZW0uRHJhd2luZy5Db2xv 127 | cltdAgAAAAgICQMAAACNAAAAjQAAAAcDAAAAAAEAAAAAAQAABBRTeXN0ZW0uRHJhd2luZy5Db2xvcgIA 128 | AAAF/P///xRTeXN0ZW0uRHJhd2luZy5Db2xvcgQAAAAEbmFtZQV2YWx1ZQprbm93bkNvbG9yBXN0YXRl 129 | AQAAAAkHBwIAAAAKAAAAAAAAAAClAAEAAfv////8////CgAAAAAAAAAApgABAAH6/////P///woAAAAA 130 | AAAAAKQAAQAB+f////z///8KAAAAAAAAAAAbAAEAAfj////8////CgAAAAAAAAAAHAABAAH3/////P// 131 | /woAAAAAAAAAAB0AAQAB9v////z///8KAAAAAAAAAAAeAAEAAfX////8////CgAAAAAAAAAAHwABAAH0 132 | /////P///woAAAAAAAAAACAAAQAB8/////z///8KAAAAAAAAAAAhAAEAAfL////8////CgAAAAAAAAAA 133 | IgABAAHx/////P///woAAAAAAAAAACMAAQAB8P////z///8KAAAAAAAAAAAkAAEAAe/////8////CgAA 134 | AAAAAAAAJQABAAHu/////P///woAAAAAAAAAACYAAQAB7f////z///8KAAAAAAAAAAAnAAEAAez////8 135 | ////CgAAAAAAAAAAKAABAAHr/////P///woAAAAAAAAAACkAAQAB6v////z///8KAAAAAAAAAAAqAAEA 136 | Aen////8////CgAAAAAAAAAAKwABAAHo/////P///woAAAAAAAAAACwAAQAB5/////z///8KAAAAAAAA 137 | AAAtAAEAAeb////8////CgAAAAAAAAAALgABAAHl/////P///woAAAAAAAAAAC8AAQAB5P////z///8K 138 | AAAAAAAAAAAwAAEAAeP////8////CgAAAAAAAAAAMQABAAHi/////P///woAAAAAAAAAADIAAQAB4f// 139 | //z///8KAAAAAAAAAAAzAAEAAeD////8////CgAAAAAAAAAANAABAAHf/////P///woAAAAAAAAAADUA 140 | AQAB3v////z///8KAAAAAAAAAAA2AAEAAd3////8////CgAAAAAAAAAANwABAAHc/////P///woAAAAA 141 | AAAAADgAAQAB2/////z///8KAAAAAAAAAAA5AAEAAdr////8////CgAAAAAAAAAAOgABAAHZ/////P// 142 | /woAAAAAAAAAADsAAQAB2P////z///8KAAAAAAAAAAA8AAEAAdf////8////CgAAAAAAAAAAPQABAAHW 143 | /////P///woAAAAAAAAAAD4AAQAB1f////z///8KAAAAAAAAAAA/AAEAAdT////8////CgAAAAAAAAAA 144 | QAABAAHT/////P///woAAAAAAAAAAEEAAQAB0v////z///8KAAAAAAAAAABCAAEAAdH////8////CgAA 145 | AAAAAAAAQwABAAHQ/////P///woAAAAAAAAAAEQAAQABz/////z///8KAAAAAAAAAABFAAEAAc7////8 146 | ////CgAAAAAAAAAARgABAAHN/////P///woAAAAAAAAAAEcAAQABzP////z///8KAAAAAAAAAABIAAEA 147 | Acv////8////CgAAAAAAAAAASQABAAHK/////P///woAAAAAAAAAAEoAAQAByf////z///8KAAAAAAAA 148 | AABLAAEAAcj////8////CgAAAAAAAAAATAABAAHH/////P///woAAAAAAAAAAE0AAQABxv////z///8K 149 | AAAAAAAAAABOAAEAAcX////8////CgAAAAAAAAAATwABAAHE/////P///woAAAAAAAAAAFAAAQABw/// 150 | //z///8KAAAAAAAAAABRAAEAAcL////8////CgAAAAAAAAAAUgABAAHB/////P///woAAAAAAAAAAFMA 151 | AQABwP////z///8KAAAAAAAAAABUAAEAAb/////8////CgAAAAAAAAAAVQABAAG+/////P///woAAAAA 152 | AAAAAFYAAQABvf////z///8KAAAAAAAAAABXAAEAAbz////8////CgAAAAAAAAAAWAABAAG7/////P// 153 | /woAAAAAAAAAAFkAAQABuv////z///8KAAAAAAAAAABaAAEAAbn////8////CgAAAAAAAAAAWwABAAG4 154 | /////P///woAAAAAAAAAAFwAAQABt/////z///8KAAAAAAAAAABdAAEAAbb////8////CgAAAAAAAAAA 155 | XgABAAG1/////P///woAAAAAAAAAAGAAAQABtP////z///8KAAAAAAAAAABfAAEAAbP////8////CgAA 156 | AAAAAAAAYQABAAGy/////P///woAAAAAAAAAAGIAAQABsf////z///8KAAAAAAAAAABjAAEAAbD////8 157 | ////CgAAAAAAAAAAZAABAAGv/////P///woAAAAAAAAAAGUAAQABrv////z///8KAAAAAAAAAABmAAEA 158 | Aa3////8////CgAAAAAAAAAAZwABAAGs/////P///woAAAAAAAAAAGgAAQABq/////z///8KAAAAAAAA 159 | AABpAAEAAar////8////CgAAAAAAAAAAagABAAGp/////P///woAAAAAAAAAAGsAAQABqP////z///8K 160 | AAAAAAAAAABsAAEAAaf////8////CgAAAAAAAAAAbQABAAGm/////P///woAAAAAAAAAAG4AAQABpf// 161 | //z///8KAAAAAAAAAABvAAEAAaT////8////CgAAAAAAAAAAcAABAAGj/////P///woAAAAAAAAAAHEA 162 | AQABov////z///8KAAAAAAAAAAByAAEAAaH////8////CgAAAAAAAAAAcwABAAGg/////P///woAAAAA 163 | AAAAAHQAAQABn/////z///8KAAAAAAAAAAB1AAEAAZ7////8////CgAAAAAAAAAAdgABAAGd/////P// 164 | /woAAAAAAAAAAHcAAQABnP////z///8KAAAAAAAAAAB4AAEAAZv////8////CgAAAAAAAAAAeQABAAGa 165 | /////P///woAAAAAAAAAAHoAAQABmf////z///8KAAAAAAAAAAB7AAEAAZj////8////CgAAAAAAAAAA 166 | fAABAAGX/////P///woAAAAAAAAAAH0AAQABlv////z///8KAAAAAAAAAAB+AAEAAZX////8////CgAA 167 | AAAAAAAAfwABAAGU/////P///woAAAAAAAAAAIAAAQABk/////z///8KAAAAAAAAAACBAAEAAZL////8 168 | ////CgAAAAAAAAAAggABAAGR/////P///woAAAAAAAAAAIMAAQABkP////z///8KAAAAAAAAAACEAAEA 169 | AY/////8////CgAAAAAAAAAAhQABAAGO/////P///woAAAAAAAAAAIYAAQABjf////z///8KAAAAAAAA 170 | AACHAAEAAYz////8////CgAAAAAAAAAAiAABAAGL/////P///woAAAAAAAAAAIkAAQABiv////z///8K 171 | AAAAAAAAAACKAAEAAYn////8////CgAAAAAAAAAAiwABAAGI/////P///woAAAAAAAAAAIwAAQABh/// 172 | //z///8KAAAAAAAAAACNAAEAAYb////8////CgAAAAAAAAAAjgABAAGF/////P///woAAAAAAAAAAI8A 173 | AQABhP////z///8KAAAAAAAAAACQAAEAAYP////8////CgAAAAAAAAAAkQABAAGC/////P///woAAAAA 174 | AAAAAJIAAQABgf////z///8KAAAAAAAAAACTAAEAAYD////8////CgAAAAAAAAAAlAABAAF//////P// 175 | /woAAAAAAAAAAJUAAQABfv////z///8KAAAAAAAAAACWAAEAAX3////8////CgAAAAAAAAAAlwABAAF8 176 | /////P///woAAAAAAAAAAJgAAQABe/////z///8KAAAAAAAAAACZAAEAAXr////8////CgAAAAAAAAAA 177 | mgABAAF5/////P///woAAAAAAAAAAJsAAQABeP////z///8KAAAAAAAAAACcAAEAAXf////8////CgAA 178 | AAAAAAAAnQABAAF2/////P///woAAAAAAAAAAJ4AAQABdf////z///8KAAAAAAAAAACfAAEAAXT////8 179 | ////CgAAAAAAAAAAoAABAAFz/////P///woAAAAAAAAAAKEAAQABcv////z///8KAAAAAAAAAACiAAEA 180 | AXH////8////CgAAAAAAAAAAowABAAFw/////P///woAAAAAAAAAAKcAAQABb/////z///8KAAAAAAAA 181 | AAAAAAAAAW7////8////CgAAAAAAAAAAAAAAAAFt/////P///woAAAAAAAAAAAAAAAABbP////z///8K 182 | AAAAAAAAAAAAAAAAAWv////8////CgAAAAAAAAAAAAAAAAFq/////P///woAAAAAAAAAAAAAAAABaf// 183 | //z///8KAAAAAAAAAAAAAAAAAWj////8////CgAAAAAAAAAAAAAAAAFn/////P///woAAAAAAAAAAAAA 184 | AAABZv////z///8KAAAAAAAAAAAAAAAAAWX////8////CgAAAAAAAAAAAAAAAAFk/////P///woAAAAA 185 | AAAAAAAAAAABY/////z///8KAAAAAAAAAAAAAAAAAWL////8////CgAAAAAAAAAAAAAAAAFh/////P// 186 | /woAAAAAAAAAAAAAAAABYP////z///8KAAAAAAAAAAAAAAAAAV/////8////CgAAAAAAAAAAAAAAAAFe 187 | /////P///woAAAAAAAAAAAAAAAABXf////z///8KAAAAAAAAAAAAAAAAAVz////8////CgAAAAAAAAAA 188 | AAAAAAFb/////P///woAAAAAAAAAAAAAAAABWv////z///8KAAAAAAAAAAAAAAAAAVn////8////CgAA 189 | AAAAAAAAAAAAAAFY/////P///woAAAAAAAAAAAAAAAABV/////z///8KAAAAAAAAAAAAAAAAAVb////8 190 | ////CgAAAAAAAAAAAAAAAAFV/////P///woAAAAAAAAAAAAAAAABVP////z///8KAAAAAAAAAAAAAAAA 191 | AVP////8////CgAAAAAAAAAAAAAAAAFS/////P///woAAAAAAAAAAAAAAAABUf////z///8KAAAAAAAA 192 | AAAAAAAAAVD////8////CgAAAAAAAAAAAAAAAAFP/////P///woAAAAAAAAAAAAAAAABTv////z///8K 193 | AAAAAAAAAAAAAAAAAU3////8////CgAAAAAAAAAAAAAAAAFM/////P///woAAAAAAAAAAAAAAAABS/// 194 | //z///8KAAAAAAAAAAAAAAAAAUr////8////CgAAAAAAAAAAAAAAAAFJ/////P///woAAAAAAAAAAAAA 195 | AAABSP////z///8KAAAAAAAAAAAAAAAAAUf////8////CgAAAAAAAAAAAAAAAAFG/////P///woAAAAA 196 | AAAAAAAAAAABRf////z///8KAAAAAAAAAAAAAAAAAUT////8////CgAAAAAAAAAAAAAAAAFD/////P// 197 | /woAAAAAAAAAAAAAAAABQv////z///8KAAAAAAAAAAAAAAAAAUH////8////CgAAAAAAAAAAAAAAAAFA 198 | /////P///woAAAAAAAAAAAAAAAABP/////z///8KAAAAAAAAAAAAAAAAAT7////8////CgAAAAAAAAAA 199 | AAAAAAE9/////P///woAAAAAAAAAAAAAAAABPP////z///8KAAAAAAAAAAAAAAAAATv////8////CgAA 200 | AAAAAAAAAAAAAAE6/////P///woAAAAAAAAAAAAAAAABOf////z///8KAAAAAAAAAAAAAAAAATj////8 201 | ////CgAAAAAAAAAAAAAAAAE3/////P///woAAAAAAAAAAAAAAAABNv////z///8KAAAAAAAAAAAAAAAA 202 | ATX////8////CgAAAAAAAAAAAAAAAAE0/////P///woAAAAAAAAAAAAAAAABM/////z///8KAAAAAAAA 203 | AAAAAAAAATL////8////CgAAAAAAAAAAAAAAAAEx/////P///woAAAAAAAAAAAAAAAABMP////z///8K 204 | AAAAAAAAAAAAAAAAAS/////8////CgAAAAAAAAAAAAAAAAEu/////P///woAAAAAAAAAAAAAAAABLf// 205 | //z///8KAAAAAAAAAAAAAAAAASz////8////CgAAAAAAAAAAAAAAAAEr/////P///woAAAAAAAAAAAAA 206 | AAABKv////z///8KAAAAAAAAAAAAAAAAASn////8////CgAAAAAAAAAAAAAAAAEo/////P///woAAAAA 207 | AAAAAAAAAAABJ/////z///8KAAAAAAAAAAAAAAAAASb////8////CgAAAAAAAAAAAAAAAAEl/////P// 208 | /woAAAAAAAAAAAAAAAABJP////z///8KAAAAAAAAAAAAAAAAASP////8////CgAAAAAAAAAAAAAAAAEi 209 | /////P///woAAAAAAAAAAAAAAAABIf////z///8KAAAAAAAAAAAAAAAAASD////8////CgAAAAAAAAAA 210 | AAAAAAEf/////P///woAAAAAAAAAAAAAAAABHv////z///8KAAAAAAAAAAAAAAAAAR3////8////CgAA 211 | AAAAAAAAAAAAAAEc/////P///woAAAAAAAAAAAAAAAABG/////z///8KAAAAAAAAAAAAAAAAARr////8 212 | ////CgAAAAAAAAAAAAAAAAEZ/////P///woAAAAAAAAAAAAAAAABGP////z///8KAAAAAAAAAAAAAAAA 213 | ARf////8////CgAAAAAAAAAAAAAAAAEW/////P///woAAAAAAAAAAAAAAAABFf////z///8KAAAAAAAA 214 | AAAAAAAAART////8////CgAAAAAAAAAAAAAAAAET/////P///woAAAAAAAAAAAAAAAABEv////z///8K 215 | AAAAAAAAAAAAAAAAARH////8////CgAAAAAAAAAAAAAAAAEQ/////P///woAAAAAAAAAAAAAAAABD/// 216 | //z///8KAAAAAAAAAAAAAAAAAQ7////8////CgAAAAAAAAAAAAAAAAEN/////P///woAAAAAAAAAAAAA 217 | AAABDP////z///8KAAAAAAAAAAAAAAAAAQv////8////CgAAAAAAAAAAAAAAAAEK/////P///woAAAAA 218 | AAAAAAAAAAABCf////z///8KAAAAAAAAAAAAAAAAAQj////8////CgAAAAAAAAAAAAAAAAEH/////P// 219 | /woAAAAAAAAAAAAAAAABBv////z///8KAAAAAAAAAAAAAAAAAQX////8////CgAAAAAAAAAAAAAAAAEE 220 | /////P///woAAAAAAAAAAAAAAAABA/////z///8KAAAAAAAAAAAAAAAAAQL////8////CgAAAAAAAAAA 221 | AAAAAAEB/////P///woAAAAAAAAAAAAAAAABAP////z///8KAAAAAAAAAAAAAAAAAf/+///8////CgAA 222 | AAAAAAAAAAAAAAH+/v///P///woAAAAAAAAAAAAAAAAB/f7///z///8KAAAAAAAAAAAAAAAACw== 223 | 224 | 225 | --------------------------------------------------------------------------------