C#学习笔记-观察者模式
题目1:几个同事为了在上班期间偷偷看休息,做点其他的事情,就和小秘偷偷联系了一下,如果老板回来了,就麻烦小秘偷偷通知一声,这样方便大家及时变更自己的工作状态。
分析:
根据题目分析,首先明确,肯定会有两个类:小秘类和同事类,分别描述与记录两种类型的人和行为。
需要注意的是:小秘与同事构建联系的时候,一个小秘可能对应多位同事,所以这时需要利用List<>。
实现:
class Program
{
static void Main(string[] args)
{
Secretary lady = new Secretary();
StockObserver num1 = new StockObserver("A", lady);
StockObserver num2 = new StockObserver("B", lady); lady.Attach(num1);
lady.Attach(num2); lady.SecretAction="boss is back";
lady.Notify(); Console.Read();
}
} /// <summary>
/// 小秘
/// 1.记下需要联系的同事们List<StockObserver>
/// 2.增加需要联系的人员
/// 3.减少联系人员(有可能没有通知到,有可能人员辞职等)
/// 4.秘密通知同事,老板回来了
/// </summary>
class Secretary
{
IList<StockObserver> stockOb = new List<StockObserver>();
private string action; public string SecretAction
{
get
{
return action;
} set
{
action = value;
}
} //增加需要联系的人员
public void Attach(StockObserver ob)
{
stockOb.Add(ob);
} //减少需要联系的人员
public void Detach(StockObserver ob)
{
stockOb.Remove(ob);
} //小秘通知了同事后,同事赶紧自行更改工作状态
public void Notify()
{
foreach (StockObserver o in stockOb)
o.Update();
}
} /// <summary>
/// 看股票的同事
/// 1.联系小秘,和小秘保持良好关系
/// 2.根据小秘的偷偷通知修改自己的工作状态
/// </summary>
class StockObserver
{
private string name;
private Secretary sec; public StockObserver(string name,Secretary sec)
{
this.name = name;
this.sec = sec;
}
public void Update()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sec.SecretAction, name);
}
}
题目2:由于同事们人数众多,所以大家休闲的方式并不一致。
分析:
同事们的休闲方式不同,他们彼此之间存在共同点与不同点。
他们的共同点在于都需要与小秘联系且更新工作状态,同时他们的不同点也在于更新工作状态。
所以相同点就不需要在子类中赘述,所以通过抽象类来将不同的方法设为抽象即可。
实现:
class Program
{
static void Main(string[] args)
{
Secretary lady = new Secretary();
StockObserver num1 = new StockObserver("A", lady);
NBAObserver num2 = new NBAObserver("B", lady); lady.Attach(num1);
lady.Attach(num2); lady.SecretAction = "boss is back";
lady.Notify(); Console.Read();
}
} /// <summary>
/// 小秘
/// 1.记下需要联系的同事们List<StockObserver>
/// 2.增加需要联系的人员
/// 3.减少联系人员(有可能没有通知到,有可能人员辞职等)
/// 4.秘密通知同事,老板回来了
/// </summary>
class Secretary
{
IList<Observers> observers = new List<Observers>();
private string action; public string SecretAction
{
get
{
return action;
} set
{
action = value;
}
} //增加需要联系的人员
public void Attach(Observers ob)
{
observers.Add(ob);
} //减少需要联系的人员
public void Detach(Observers ob)
{
observers.Remove(ob);
} //小秘通知了同事后,同事赶紧自行更改工作状态
public void Notify()
{
foreach (Observers o in observers)
o.Update();
}
} /// <summary>
/// 观察者类
/// 抽象类
/// 偷偷玩的同事的状态都不同,他们的共同点就是1.与小秘联系,2.更新工作状态
/// 不同点在于更新状态前不同,所以更新工作状态设置为抽象方法即可
/// </summary>
abstract class Observers
{
protected string name;
protected Secretary sec; public Observers(string name,Secretary sec)
{
this.name = name;
this.sec = sec;
} public abstract void Update();
} /// <summary>
/// 看股票的同事
/// 继承于观察者类
/// 根据小秘的偷偷通知修改自己的工作状态
/// </summary>
class StockObserver:Observers
{
public StockObserver(string name, Secretary sec)
: base(name, sec)
{
} public override void Update()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sec.SecretAction,name);
}
} /// <summary>
/// 看NBA节目的同事
/// 继承于观察者类
/// 根据小秘的偷偷通知修改自己的工作状态
/// </summary>
class NBAObserver : Observers
{
public NBAObserver(string name, Secretary sec)
: base(name, sec)
{
} public override void Update()
{
Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sec.SecretAction, name);
}
}
题目3:如果小秘突然有事情变得特别忙的时候,就没有了通知者,而此刻老板突然回来了,所以老板本身就变成了临时的通知者。
分析:
老板本身变成了临时的通知者,虽然这个故事很不幸,但是客观分析,此刻老板的作用于小秘是一样的,所以老板应该和小秘继承于同一种父类。
由于老板需要与观察者联系,而此刻的观察者已是抽象类,所以老板的父类不能再为抽象类了。
原因如下:
故此,老板和小秘只能通过接口来实现了。
实现:
class Program
{
static void Main(string[] args)
{
Boss boss = new Boss(); Secretary lady = new Secretary();
StockObserver num1 = new StockObserver("A", lady);
NBAObserver num2 = new NBAObserver("B", lady); //lady没来的及通知两位同事
lady.Detach(num1);
lady.Detach(num2); //现在的通知者就变成了boss
boss.Attach(num1);
boss.Attach(num2); //num2没有看见boss回来,所以boss没来的及通知他
boss.Detach(num2); boss.SecretAction = "boss is back";
boss.Notify(); Console.Read();
}
} /// <summary>
/// 通知者的接口
/// 不能用抽象类
/// </summary>
interface Subject
{
void Attach(Observers ob);
void Detach(Observers ob);
void Notify();
string SecretAction
{
get;set;
}
} class Boss : Subject
{
IList<Observers> observers = new List<Observers>();
private string action; public string SecretAction
{
get
{
return action;
} set
{
action = value;
}
} //增加需要联系的人员
public void Attach(Observers ob)
{
observers.Add(ob);
} //减少需要联系的人员
public void Detach(Observers ob)
{
observers.Remove(ob);
} //大家看见boss回来后,同事赶紧自行更改工作状态
public void Notify()
{
foreach (Observers o in observers)
o.Update();
}
} /// <summary>
/// 小秘:继承于接口
/// 1.记下需要联系的同事们List<StockObserver>
/// 2.增加需要联系的人员
/// 3.减少联系人员(有可能没有通知到,有可能人员辞职等)
/// 4.秘密通知同事,老板回来了
/// </summary>
class Secretary:Subject
{
IList<Observers> observers = new List<Observers>();
private string action; public string SecretAction
{
get
{
return action;
} set
{
action = value;
}
} //增加需要联系的人员
public void Attach(Observers ob)
{
observers.Add(ob);
} //减少需要联系的人员
public void Detach(Observers ob)
{
observers.Remove(ob);
} //小秘通知了同事后,同事赶紧自行更改工作状态
public void Notify()
{
foreach (Observers o in observers)
o.Update();
}
} /// <summary>
/// 观察者类
/// 抽象类
/// 偷偷玩的同事的状态都不同,他们的共同点就是1.与小秘联系,2.更新工作状态
/// 不同点在于更新状态前不同,所以更新工作状态设置为抽象方法即可
/// </summary>
abstract class Observers
{
protected string name;
protected Secretary sec; public Observers(string name, Secretary sec)
{
this.name = name;
this.sec = sec;
} public abstract void Update();
} /// <summary>
/// 看股票的同事
/// 继承于观察者类
/// 根据小秘的偷偷通知修改自己的工作状态
/// </summary>
class StockObserver : Observers
{
public StockObserver(string name, Secretary sec)
: base(name, sec)
{
} public override void Update()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sec.SecretAction, name);
}
} /// <summary>
/// 看NBA节目的同事
/// 继承于观察者类
/// 根据小秘的偷偷通知修改自己的工作状态
/// </summary>
class NBAObserver : Observers
{
public NBAObserver(string name, Secretary sec)
: base(name, sec)
{
} public override void Update()
{
Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sec.SecretAction, name);
}
}
附:
实现:
class Program
{
static void Main(string[] args)
{
Boss boss = new Boss();
Secretary lady = new Secretary(); StockObserver num1 = new StockObserver("A", boss);
NBAObserver num2 = new NBAObserver("B", boss); //将“看股票”的“关闭股票程序”方法和“看NBA者”的“关闭NBA直播”的方法
//挂钩到老板的“更新”上,也就是将两种不同类的不同方法委托给老板类的更新了。
boss.Update += new EventHandler(num1.CloseStockMarket);
boss.Update += new EventHandler(num2.CloseNBADirectSeeding); boss.SecretAction = "boss is back";
boss.Notify(); Console.Read();
}
} /// <summary>
/// 通知者的接口
/// 不能用抽象类
/// 现在抽象通知者由于不下网依赖抽象观察者,所以“增加”和“减少”的方法就没有必要了
/// </summary>
interface Subject
{
void Notify();
string SecretAction
{
get; set;
}
} /// <summary>
/// 委托就是一种引用方法的类型。
/// 一旦为委托分配了方法,委托将于该方法具有完全相同的行为
/// 委托方法的使用可以像任何其他方法一样,具有参数和返回值。
/// 委托可以看做是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数
///
/// 一个委托可以搭载多个方法,所有的方法被依次唤起
/// 最重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类
///
/// 委托对象所搭载的所有方法必须具有相同的原型和形式,也就是有相同的参数列表和返回值类型
/// </summary>
delegate void EventHandler(); //委托 class Boss : Subject
{
public event EventHandler Update; private string action; public string SecretAction
{
get
{
return action;
} set
{
action = value;
}
} //大家看见boss回来后,同事赶紧自行更改工作状态
public void Notify()
{
Update();
}
} /// <summary>
/// 小秘:继承于接口
/// 1.记下需要联系的同事们List<StockObserver>
/// 2.增加需要联系的人员
/// 3.减少联系人员(有可能没有通知到,有可能人员辞职等)
/// 4.秘密通知同事,老板回来了
/// </summary>
class Secretary : Subject
{
public event EventHandler Update; private string action; public string SecretAction
{
get
{
return action;
} set
{
action = value;
}
} //小秘通知了同事后,同事赶紧自行更改工作状态
public void Notify()
{
Update();
}
} /// <summary>
/// 看股票的同事
/// 根据小秘的偷偷通知修改自己的工作状态
/// </summary>
class StockObserver
{
private string name;
private Subject sub; public StockObserver(string name,Subject sub)
{
this.name = name;
this.sub = sub;
} public void CloseStockMarket()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SecretAction, name);
}
} /// <summary>
/// 看NBA节目的同事
/// 根据小秘的偷偷通知修改自己的工作状态
/// </summary>
class NBAObserver
{
private string name;
private Subject sub; public NBAObserver(string name,Subject sub)
{
this.name = name;
this.sub = sub;
} public void CloseNBADirectSeeding()
{
Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SecretAction, name);
}
}
总结:
观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
观察者模式所做的工作其实就是在接触耦合。让耦合的双方依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
委托:就是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托可以看作是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。
一个委托可以搭载多个方法,所有方法被依次唤起。
委托对象所搭载的方法并不需要属于同一个类。
注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。
C#学习笔记-观察者模式的更多相关文章
- 《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式
装饰者模式是JDK中还有一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源代码,也是为了学习大牛们的设计思路.--- ...
- Head First Design Patterns学习笔记-观察者模式
认识观察者模式 首先来看看报纸订阅的过程 1.报社的业务就是出版报纸 2.向某家报社订阅报纸,只要他们有新报纸出版,就会送过来,只要你是他们的订户 3.当你不想再看报纸的时候,取消订阅,他们就不会再送 ...
- 学习笔记——观察者模式Observer
观察者模式,当事件发生时,调用相应观察者的方法进行“通知”.Subject中使用一个数据结构存储需要通知的观察者对象,执行Notify时,执行所有观察者的Update方法.
- Java 学习笔记 观察者模式与适配者模式 监控文件夹
2019.4.12 适配器模式,如果某个类需要实现多个方法,但是开发过程中只需要实现其中的一两个方法,直接使用该类的适配器类,复写需要实现的方法即可 观察者模式:有多个观察者observe观察一个主体 ...
- Java-马士兵设计模式学习笔记-观察者模式-模拟Awt Button
一.概述 Java 的Awt是 Observer模式,现用Java自己模拟awt中Button的运行机制 二.代码 1.Test.java import java.text.DateFormat; i ...
- Java-马士兵设计模式学习笔记-观察者模式-AWT简单例子
1.AWT简单例子 TestFrame.java import java.awt.Button; import java.awt.Frame; import java.awt.event.Action ...
- Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式
一.概述 1.目标:读取properties文件改成单例模式 二.代码 1.Test.java class WakenUpEvent{ private long time; private Strin ...
- Java-马士兵设计模式学习笔记-观察者模式-OOD 封装Listener
一.概述 childe类中的是关联监听者dad的,若要再增加监听者,会很不方便,且要修改代码.好的方法是封装监听者类,用addListener()方法动态添加监听者 二.代码 1.Test.java ...
- Java-马士兵设计模式学习笔记-观察者模式-OOD 封装event
把小孩醒来时的具体情况封装成事件类 Test.java class WakenUpEvent{ private long time; private String location; private ...
随机推荐
- ubuntu下php不能显示中文的问题的解决过程。
在阿里的ECS上的ubuntu平台上成功的安装了apache2和php5与mysql,并进行了测试. 如图所示:
- 201521123033《Java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. answer; 2. 书面作业 本次PTA作业题集多线程 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4- ...
- 201521123074 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 Q1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现 ...
- [ JDK ] 列表转数组 toArray
<T> T[] toArray(T[] a) :该方法返回一个数组,数组元素包含了 List<T> 中的所有元素,数组中的元素顺序和 List<T> 中的元素顺序保 ...
- SpringMVC第四篇【参数绑定详讲、默认支持参数类型、自定义参数绑定、RequestParam注解】
参数绑定 我们在Controller使用方法参数接收值,就是把web端的值给接收到Controller中处理,这个过程就叫做参数绑定- 默认支持的参数类型 从上面的用法我们可以发现,我们可以使用req ...
- 【Spring源码深度解析系列 】Spring整体架构
一.Spring的整体架构和模块 二.模块分类: 1.Core Container Core Container包含有Core .Beans.Context.和Expression Language ...
- Python基础知识总结
看了一个礼拜Python的书,断断续续的看了一大半.今天刚好没有课,想着也没什么事情干,就把这几天Python总结一下,都是一些基础知识 变量和对象的引用 在python中一切都是对象,不像C,jav ...
- RAID及热备盘详解
RAID,为Redundant Arrays of Independent Disks的简称,中文为廉价冗余磁盘阵列. 一.出现的原因(RAID的优点): 它的用途主要是面向服务器,但现在的个人电脑由 ...
- React Router 按需加载+服务器渲染的闪屏问题
伴随着React协议的『妥协』(v16采用MIT),React为项目的主体,这个在短期内是不会改变的了,在平时使用过程中发现了如下这个问题: 在服务器渲染的时候,刷新页面会出现闪屏的现象(白屏一闪而过 ...
- Easy sssp
Easy sssp 时间限制: 1 Sec 内存限制: 128 MB提交: 103 解决: 20[提交][状态][讨论版] 题目描述 输入数据给出一个有N(2 < = N < = ...