C#面向抽象编程第二讲

虚幻大学 xuhss 149℃ 0评论

Python微信订餐小程序课程视频

https://blog.csdn.net/m0_56069948/article/details/122285951

Python实战量化交易理财系统

https://blog.csdn.net/m0_56069948/article/details/122285941
抽象编程怎么说呢,以观察者模式为例:

观察者模式有两个对象,一个是观察者,一个是可观察者(字面翻译很别扭observable),消息发布者(提供者)。

第一层如下,三个对象A、B、C分别有一个接收消息的方法,还有一个存储数据的字段,X就是发布消息的对象,它通过setdata方法设置自己的字段data,然后通知abc,abc如愿以偿地拿到了通知,完美!

internal class A
 {
 public int Data;
 public void Update(int data)
 {
 this.Data = data;
 }
 }

 internal class B
 {
 public int Count;
 public void Notify(int data)
 {
 this.Count = data;
 }
 }

 internal class C
 {
 public int N;
 public void Set(int data)
 {
 this.N = data;
 }
 }

 internal class X
 {
 private int data;
 public A instanceA;
 public B instanceB;
 public C instanceC;
 public void SetData(int data)
 {
 this.data = data;
 instanceA.Update(data);
 instanceB.Notify(data);
 instanceC.Set(data);
 }
 }

using ObserverOne;

A a = new A();
B b = new B();
C c = new C();

Console.WriteLine("订阅前.................");
Console.WriteLine($"a.Data = {a.Data}");
Console.WriteLine($"b.Count = {b.Count}");
Console.WriteLine($"c.N = {c.N}");

X x =new X();
x.instanceA = a;
x.instanceB = b;
x.instanceC = c;
x.SetData(10); 
Console.WriteLine("X发布data=10, 订阅后.................");
Console.WriteLine($"a.Data = {a.Data}");
Console.WriteLine($"b.Count = {b.Count}");
Console.WriteLine($"c.N = {c.N}");

再想一想,这好像不够灵活,订阅者是死的,那改进一下:

internal interface IUpdatebleObject
 {
 int Data { get; }
 void Update(int newData);
 }

 internal class A : IUpdatebleObject
 {
 public int Data => data;
 private int data;

 public void Update(int newData)
 {
 this.data = newData;
 }
 }

 internal class B : IUpdatebleObject
 {
 public int Data => data;
 private int data;
 public void Update(int newData)
 {
 this.data = newData;
 }
 }

 internal class C : IUpdatebleObject
 {
 public int Data => data;
 private int data;
 public void Update(int newData)
 {
 this.data = newData;
 }
 }

 internal class X
 {
 private IUpdatebleObject[] updates=new IUpdatebleObject[3];

 public IUpdatebleObject this[int index]
 {
 set { updates[index] = value; }
 }
 private int data;
 public void Update(int newData)
 {
 this.data = newData;
 foreach (var update in updates)
 {
 update.Update(newData);
 }
 }
 }

using ObserverTwo;

X x = new X();

IUpdatebleObject a = new A();
IUpdatebleObject b = new B();
IUpdatebleObject c = new C();
Console.WriteLine("订阅前.................");
Console.WriteLine($"a.Data = {a.Data}");
Console.WriteLine($"b.Data = {b.Data}");
Console.WriteLine($"c.Data = {c.Data}");
x[0] = a;
x[1] = b;
x[2] = c;
x.Update(10);
Console.WriteLine("X发布data=10, 订阅后.................");
Console.WriteLine($"a.Data = {a.Data}");
Console.WriteLine($"b.Data = {b.Data}");
Console.WriteLine($"c.Data = {c.Data}");

虽然写到这个例子已经很了不起了,但是对于有想法的来说还是可以继续改进,要不然怎么常挂嘴边说面对抽象编程呢,那就继续改进了:

/// 
    /// 观察者
 /// 
    /// 
    internal interface IObserver
 {
 void Update(SubjectBase subject);
 }
/// 
    /// 可观察者(发出通知的对象)
 /// 
    /// 
    internal abstract class SubjectBase
 {
 protected IList> observers = new List>();
 protected T state;
 public virtual T State => state;

 public static SubjectBase operator +(SubjectBase subject,IObserver observer)
 {
 subject.observers.Add(observer);
 return subject;
 }
 public static SubjectBase operator -(SubjectBase subject,IObserver observer)
 {
 subject.observers.Remove(observer);
 return subject;
 }

 public virtual void Notify()
 {
 foreach (var observer in observers)
 {
 observer.Update(this);
 }
 }

 public virtual void Update(T state)
 {
 this.state = state;
 Notify();
 }
 }
 internal class Observer : IObserver
 {
 public T State;

 public void Update(SubjectBase subject)
 {
 this.State = subject.State;
 }
 }
 internal class Subject:SubjectBase
 {
 }

到这里基本上可以说是把骨架搭起来了,这些可以称之为底层的代码。实现代码如下:

internal class TestObserver
 {
 public void TestMulticst()
 {
 SubjectBase<int> subject = new Subject<int>();
 Observer<int> observer1 = new Observer<int>();
 observer1.State = 10;
 Observer<int> observer2 = new Observer<int>();
 observer2.State = 20;
 subject += observer1;
 subject += observer2;
 subject.Update(1);
 Console.WriteLine($"observer1.State={observer1.State} observer2.State={observer2.State}");
 subject -= observer1;
 subject.Update(100);
 Console.WriteLine($"update state = 100, observer1.State={observer1.State} observer2.State={observer2.State}");
 }

 public void TestMultiSubject()
 {
 SubjectBase<string> subject1 = new Subject<string>();
 SubjectBase<string> subject2 = new Subject<string>();
 Observer<string> observer1 = new Observer<string>();
 observer1.State = "运动";
 Console.WriteLine($"observer1.State={observer1.State}");
 subject1 += observer1;
 subject2 += observer1;
 subject1.Update("看电影");
 Console.WriteLine($"observer1.State={observer1.State}");
 subject2.Update("喝茶");
 Console.WriteLine($"observer1.State={observer1.State}");

 subject1 -= observer1;
 subject2 -= observer1;
 observer1.State = "休息";
 subject1 -= observer1;
 subject2 -= observer1;
 Console.WriteLine($"observer1.State={observer1.State}");
 }
 }
using ObserverThree;

//new TestObserver().TestMulticst();

new TestObserver().TestMultiSubject();

到这里基本上就完成了任务,也就可以结束了。但是,学习需要深度也需要宽度,所以观察者模式在C#可以通过事件来实现一样的效果。下面就看下上面写这么多的代码用事件怎么写呢,这里的实例稍作变化,实现改变名字通知观察者,这里观察者就是控制台了,打印通知:

  internal class UserEventArgs:EventArgs
 {
 private string name;
 public string Name => name;

 public UserEventArgs(string name)
 {
 this.name = name;
 }

 }
 internal class User
 {
 public event EventHandler NameChanged;
 private string name;
 public string Name
 {
 get { return name; }
 set
 {
 name = value;
 NameChanged?.Invoke(this, new UserEventArgs(value));
 }
 }
 }
using ObserverFour;

User user = new User();
user.NameChanged += OnNameChanged;
user.Name = "joe";

void OnNameChanged(object sender, UserEventArgs args)
{
 Console.WriteLine($"{args.Name} Changed ");
}

再放一个麻烦一点的例子,字典新增的通知(监听)事件:

 internal class DictionaryEventArgs : EventArgs
 {
 private TKey key;
 private TValue value;
 public DictionaryEventArgs(TKey key,TValue value)
 {
 this.key = key;
 this.value = value;
 }

 public TKey Key => key;
 public TValue Value => value;
 }
 internal interface IObserverableDictionary:IDictionary
 {
 EventHandler> NewItemAdded { get; set; }
 }
 internal class ObserverableDictionary : Dictionary, IObserverableDictionary
 {
 protected EventHandler> newItemAdded;
 public EventHandler> NewItemAdded { get => newItemAdded;set=> newItemAdded = value;}
 public new void Add(TKey key,TValue value)
 {
 base.Add(key, value);
 if(NewItemAdded != null)
 NewItemAdded(this, new DictionaryEventArgs(key, value)); 
 }
 }
using ObserverFive;

string key = "hello";
string value = "world";

IObserverableDictionary<string,string> dictionary = new ObserverableDictionary<string,string>();
dictionary.NewItemAdded += Validate;
dictionary.Add(key, value);

 void Validate(object sender, DictionaryEventArgs<string,string> args)
{
 Console.WriteLine($"{args.Key} {args.Value}");
}

事件说完了!再回头看看观察者设计模式。

微软已经很重视观察者模式这个设计,把IObserver、IObservable集成到runtime里面去了,也就是基类库里面。aspnetcore框架也有用到这个,比如日志模块。所以感觉有必要了解一下,放个小例子作为结束:

  internal class Message
 {
 public string Notify { get; set; }
 }
internal class Teacher : IObservable
 {
 private readonly List> \_observers;
 public Teacher()
 {
 \_observers = new List>();
 }
 public IDisposable Subscribe(IObserver observer)
 {
 \_observers.Add(observer);
 return new Unsubscribe(observer, \_observers);
 }

 public void SendMessage(string message)
 {
 foreach (var observer in \_observers)
 {
 observer.OnNext(new Message() { Notify = "message" });
 }
 }
 public void OnCompleted()
 {
 foreach (var observer in \_observers)
 {
 observer.OnCompleted();
 }
 \_observers.Clear();
 }
 }

 internal class Unsubscribe:IDisposable
 {
 private readonly IObserver \_observer;
 private readonly List> \_observers;
 public Unsubscribe(IObserver observer, List> observers)
 {
 this.\_observers = observers;
 this.\_observer = observer;
 }

 public void Dispose()
 {
 if(\_observers.Contains(\_observer))
 \_observers.Remove(\_observer);
 }
 }
 internal abstract class Student : IObserver
 {
 private
 string name;
 public Student(string name)
 {
 this.name = name;
 }
 private IDisposable \_unsubscribe;
 public virtual void OnCompleted()
 {
 Console.WriteLine("放学了...");
 }

 public virtual void OnError(Exception error)
 {
 Console.WriteLine("生病了...");
 }

 public virtual void OnNext(Message value)
 {
 Console.WriteLine($"大家好: 我是 {name} -\_- ");
 Console.WriteLine($"老师说:{value.Notify}");
 }

 public virtual void Subscribe(IObservable obserable)
 {
 if (obserable != null)
 \_unsubscribe = obserable.Subscribe(this);
 }
 }
 internal class StudentZhang : Student
 {
 public StudentZhang(string name) : base(name)
 {
 }
 }

 internal class StudentLi : Student
 {
 public StudentLi(string name) : base(name)
 {
 }
 }
using ObserverSeven;

Teacher teacher = new Teacher();
teacher.Subscribe(new StudentLi("李逵"));
teacher.Subscribe(new StudentZhang("张麻子"));
teacher.SendMessage("明天放假");
teacher.OnCompleted();

//这里学生是多个,也定义可以多个老师,实现多对多关系

示例代码:

exercise/发布订阅And出版预定_EventBus_Observer/Observer/Observer at master · liuzhixin405/exercise (github.com)

转载请注明:xuhss » C#面向抽象编程第二讲

喜欢 (0)

您必须 登录 才能发表评论!