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 ...
随机推荐
- Python[小甲鱼003小插曲之变量和字符串]
>>>teacher = 3 >>>teacher 3 #在定义了一个变量后可以之间输入整个变量即可访问这个变量. >>> teache ...
- ZIP格式
总体格式 分文件头+文件压缩数据 中心目录+中心目录记录结束符 1.分文件头信息 0X 50 4b 03 04 分文件头信息标志,一般是zip文件的开头,可以通过这个判断文件格式 14 00 解压缩所 ...
- 201521123045 《Java程序设计》第12周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...
- 201521123031 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...
- returned a response status of 403 OR 409
当我们使用jersy把图片上传到我们的图片服务器中[tomcat],我们可能会有以下的错误: returned a response status of 403 OR 409 403和409我都遇到过 ...
- Elasticsearch 的分页报错 result window is too large
检查自己分页查询的代码 Pageable pageable = new PageRequest(0, 10000); searchQuery.setPageable(pageable); // 分页效 ...
- jz2440重新分区
在购买开发板的时候,板子上已经烧写好了bootloader.内核和文件系统.但是在具体使用时,发现板子上划分的内核分区只有2M,但是我编译出来的内核大于2M,于是将内核烧写到nandflash上面时会 ...
- Codeforces Round #436 (Div. 2) C. Bus
http://codeforces.com/contest/864/problem/C 题意: 坐标轴上有x = 0和 x = a两点,汽车从0到a之后掉头返回,从a到0之后又掉头驶向a...从0到a ...
- Vuforia开发完全指南---License Manager和Target Manager详解
License Manager和Target Manager License Manager 对于每一个用Vuforia开发的AR程序来说,都有一个唯一的license key,在Unity中必须首先 ...
- MySQL所学所思所想
MySQL更改线上配置方案思想:原则上,需要备机.备份工作准备到位,有参数调优配置方案.有配置回退方案.有应急切换备机方案.以上方案评审无问题,然后可以和客户约定实施的时间.服务中断时间,先向客户侧申 ...