CSharp: Observer Pattern in donet core 3
/// <summary>
///观察者模式 Observer Pattern 亦称: 事件订阅者、监听者、Event-Subscriber、Listener、Observe
/// geovindu,Geovin Du eidt
///
/// </summary>
interface IObserver
{
/// <summary>
///
/// </summary>
/// <param name="celeb">对象</param>
void Update(ICelebrity celeb);
}
/// <summary>
/// /
/// </summary>
class ObserverType1 : IObserver
{
/// <summary>
/// 名称
/// </summary>
string nameOfObserver;
/// <summary>
/// /
/// </summary>
/// <param name="name">输入名称</param>
public ObserverType1(String name)
{
this.nameOfObserver = name;
}
/// <summary>
/// 更新
/// </summary>
/// <param name="celeb"></param>
public void Update(ICelebrity celeb)
{
Console.WriteLine($"{nameOfObserver} has received(接收) an alert from {celeb.Name}.Updated value is(更新标志值): {celeb.Flag}");
}
}
/// <summary>
///
/// </summary>
class ObserverType2 : IObserver
{
/// <summary>
/// 名称
/// </summary>
string nameOfObserver;
/// <summary>
///
/// </summary>
/// <param name="name">输入名称</param>
public ObserverType2(String name)
{
this.nameOfObserver = name;
}
/// <summary>
/// 更新
/// </summary>
/// <param name="celeb"></param>
public void Update(ICelebrity celeb)
{
Console.WriteLine($"{nameOfObserver} notified(通知).Inside {celeb.Name}, the updated value is: {celeb.Flag}");
}
}
/// <summary>
///
/// </summary>
interface ICelebrity
{
/// <summary>
/// Name of Subject
/// 名称
/// </summary>
string Name { get; }
/// <summary>
/// 标记
/// </summary>
int Flag { get; set; }
/// <summary>
/// To register
/// 注册
/// </summary>
/// <param name="o"></param>
void Register(IObserver o);
/// <summary>
/// To Unregister
/// 取消注册
/// </summary>
/// <param name="o"></param>
void Unregister(IObserver o);
///<summary>
///To notify registered users
///注册用户
/// </summary>
void NotifyRegisteredUsers();
}
/// <summary>
///
/// </summary>
class Celebrity : ICelebrity
{
/// <summary>
/// 对像数列
/// </summary>
List<IObserver> observerList = new List<IObserver>();
/// <summary>
/// 标记
/// </summary>
private int flag;
/// <summary>
/// 标记
/// </summary>
public int Flag
{
get
{
return flag;
}
set
{
flag = value;
//Flag value changed. So notify observer(s).
NotifyRegisteredUsers();
}
}
/// <summary>
///
/// </summary>
private string name;
/// <summary>
///
/// </summary>
/// <param name="name">输入名称</param>
public Celebrity(string name)
{
this.name = name;
}
//public string Name
//{
// get
// {
// return name;
// }
//}
//Or, simply use expression bodied
//properties(C#6.0 onwards)
/// <summary>
///
/// </summary>
public string Name => name;
/// <summary>
/// To register an observer.
/// </summary>
/// <param name="anObserver">对象</param>
public void Register(IObserver anObserver)
{
observerList.Add(anObserver);
}
/// <summary>
/// To unregister an observer.
/// </summary>
/// <param name="anObserver"></param>
public void Unregister(IObserver anObserver)
{
observerList.Remove(anObserver);
}
/// <summary>
/// Notify all registered observers.
/// </summary>
public void NotifyRegisteredUsers()
{
foreach (IObserver observer in observerList)
{
observer.Update(this);
}
}
}
/// <summary>
///观察者模式 Observer Pattern 亦称: 事件订阅者、监听者、Event-Subscriber、Listener、Observe
/// geovindu,Geovin Du eidt
/// 产品
/// </summary>
public class Product : INotifyPropertyChanged
{
/// <summary>
/// 名特
/// </summary>
private string name;
/// <summary>
/// 名称
/// </summary>
public string Name
{
get => name;
set
{
if (value == name) return; // critical
name = value;
OnPropertyChanged();
}
}
/// <summary>
///
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
///
/// </summary>
/// <param name="propertyName"></param>
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(
[CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propertyName));
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"产品名称: {Name}";
}
}
/// <summary>
/// 窗口
/// </summary>
public class Window : INotifyPropertyChanged
{
/// <summary>
///
/// </summary>
private string productName;
/// <summary>
///
/// </summary>
public string ProductName
{
get => productName;
set
{
if (value == productName) return; // critical
productName = value;
OnPropertyChanged();
}
}
/// <summary>
///
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
///
/// </summary>
/// <param name="propertyName"></param>
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(
[CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propertyName));
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"窗口: {ProductName}";
}
}
/// <summary>
///
/// </summary>
public sealed class BidirectionalBinding : IDisposable
{
/// <summary>
///
/// </summary>
private bool disposed;
/// <summary>
///
/// </summary>
/// <param name="first"></param>
/// <param name="firstProperty"></param>
/// <param name="second"></param>
/// <param name="secondProperty"></param>
public BidirectionalBinding(
INotifyPropertyChanged first,
Expression<Func<object>> firstProperty,
INotifyPropertyChanged second,
Expression<Func<object>> secondProperty)
{
if (firstProperty.Body is MemberExpression firstExpr
&& secondProperty.Body is MemberExpression secondExpr)
{
if (firstExpr.Member is PropertyInfo firstProp
&& secondExpr.Member is PropertyInfo secondProp)
{
first.PropertyChanged += (sender, args) =>
{
if (!disposed)
{
secondProp.SetValue(second, firstProp.GetValue(first));
}
};
second.PropertyChanged += (sender, args) =>
{
if (!disposed)
{
firstProp.SetValue(first, secondProp.GetValue(second));
}
};
}
}
}
/// <summary>
///
/// </summary>
public void Dispose()
{
disposed = true;
}
}
调用:
//观察者模式 Observer Pattern
Console.WriteLine("***观察者模式 Observer Pattern Demonstration.***\n");
//We have 4 observers-2 of them are ObserverType1, 1 is of ObserverType2
IObserver myObserver1 = new ObserverType1("刘二");
IObserver myObserver2 = new ObserverType1("刘三");
IObserver myObserver3 = new ObserverType2("刘四");
IObserver myObserver4 = new ObserverType2("刘五");
Console.WriteLine("Working with first celebrity now.");
ICelebrity celebrity = new Celebrity("Celebrity名人-1组");
//Registering the observers-Roy,Kevin,Bose
celebrity.Register(myObserver1);
celebrity.Register(myObserver2);
celebrity.Register(myObserver3);
Console.WriteLine(" Celebrity-1 is setting Flag 设置标志 = 5.");
celebrity.Flag = 5;
/*
Kevin doesn't want to get further notification.
So, unregistering the observer(Kevin)).
*/
Console.WriteLine("\nCelebrity-名人1组 is removing(移除) 刘三 from the observer list now.");
celebrity.Unregister(myObserver2);
//No notification is sent to Kevin this time. He has unregistered.
Console.WriteLine("\n Celebrity-名人1组 is setting Flag 设置标志= 50.");
celebrity.Flag = 50;
//Kevin is registering himself again
celebrity.Register(myObserver2);
Console.WriteLine("\n Celebrity-名人1组 is setting Flag 设置标志= 100.");
celebrity.Flag = 100;
Console.WriteLine("\n Working with another celebrity now.");
//Creating another celebrity
ICelebrity celebrity2 = new Celebrity("Celebrity-名人2组");
//Registering the observers-Roy and Jacklin
celebrity2.Register(myObserver1);
celebrity2.Register(myObserver4);
Console.WriteLine("\n --Celebrity-名人2组 is setting Flag value as设置标志 500.--");
celebrity2.Flag = 500;
//
var product = new Product { Name = "书" };
var window = new Window { ProductName = "书" };
// want to ensure that when product name changes
// in one component, it also changes in another
product.PropertyChanged += (sender, eventArgs) =>
{
if (eventArgs.PropertyName == "Name")
{
Console.WriteLine("Name changed in Product");
window.ProductName = product.Name;
Console.WriteLine("changed 1." + product);
Console.WriteLine("changed 1." + window);
}
};
window.PropertyChanged += (sender, eventArgs) =>
{
if (eventArgs.PropertyName == "ProductName")
{
Console.WriteLine("Name changed in Window");
product.Name = window.ProductName;
Console.WriteLine("changed 2." + product);
Console.WriteLine("changed 2." + window);
}
};
using var binding = new BidirectionalBinding(
product,
() => product.Name,
window,
() => window.ProductName);
Console.WriteLine("1."+product); //书
Console.WriteLine("2."+window);
// there is no infinite loop because of
// self-assignment guard
product.Name = "桌子";
window.ProductName = "椅子";
Console.WriteLine(product);
Console.WriteLine(window);
Console.ReadKey();
输出:
***观察者模式 Observer Pattern Demonstration.*** Working with first celebrity now. Celebrity-1 is setting Flag 设置标志 = 5. 刘二 has received(接收) an alert from Celebrity名人-1组.Updated value is(更新标志值): 5 刘三 has received(接收) an alert from Celebrity名人-1组.Updated value is(更新标志值): 5 刘四 notified(通知).Inside Celebrity名人-1组, the updated value is: 5 Celebrity-名人1组 is removing(移除) 刘三 from the observer list now. Celebrity-名人1组 is setting Flag 设置标志= 50. 刘二 has received(接收) an alert from Celebrity名人-1组.Updated value is(更新标志值): 50 刘四 notified(通知).Inside Celebrity名人-1组, the updated value is: 50 Celebrity-名人1组 is setting Flag 设置标志= 100. 刘二 has received(接收) an alert from Celebrity名人-1组.Updated value is(更新标志值): 100 刘四 notified(通知).Inside Celebrity名人-1组, the updated value is: 100 刘三 has received(接收) an alert from Celebrity名人-1组.Updated value is(更新标志值): 100 Working with another celebrity now. --Celebrity-名人2组 is setting Flag value as设置标志 500.-- 刘二 has received(接收) an alert from Celebrity-名人2组.Updated value is(更新标志值): 500 刘五 notified(通知).Inside Celebrity-名人2组, the updated value is: 500 1.产品名称: 书 2.窗口: 书 Name changed in Product Name changed in Window changed 2.产品名称: 桌子 changed 2.窗口: 桌子 changed 1.产品名称: 桌子 changed 1.窗口: 桌子 Name changed in Window Name changed in Product changed 1.产品名称: 椅子 changed 1.窗口: 椅子 changed 2.产品名称: 椅子 changed 2.窗口: 椅子 产品名称: 椅子 窗口: 椅子
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号