题目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#学习笔记-观察者模式的更多相关文章

  1. 《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式

    装饰者模式是JDK中还有一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源代码,也是为了学习大牛们的设计思路.--- ...

  2. Head First Design Patterns学习笔记-观察者模式

    认识观察者模式 首先来看看报纸订阅的过程 1.报社的业务就是出版报纸 2.向某家报社订阅报纸,只要他们有新报纸出版,就会送过来,只要你是他们的订户 3.当你不想再看报纸的时候,取消订阅,他们就不会再送 ...

  3. 学习笔记——观察者模式Observer

    观察者模式,当事件发生时,调用相应观察者的方法进行“通知”.Subject中使用一个数据结构存储需要通知的观察者对象,执行Notify时,执行所有观察者的Update方法.

  4. Java 学习笔记 观察者模式与适配者模式 监控文件夹

    2019.4.12 适配器模式,如果某个类需要实现多个方法,但是开发过程中只需要实现其中的一两个方法,直接使用该类的适配器类,复写需要实现的方法即可 观察者模式:有多个观察者observe观察一个主体 ...

  5. Java-马士兵设计模式学习笔记-观察者模式-模拟Awt Button

    一.概述 Java 的Awt是 Observer模式,现用Java自己模拟awt中Button的运行机制 二.代码 1.Test.java import java.text.DateFormat; i ...

  6. Java-马士兵设计模式学习笔记-观察者模式-AWT简单例子

    1.AWT简单例子 TestFrame.java import java.awt.Button; import java.awt.Frame; import java.awt.event.Action ...

  7. Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式

    一.概述 1.目标:读取properties文件改成单例模式 二.代码 1.Test.java class WakenUpEvent{ private long time; private Strin ...

  8. Java-马士兵设计模式学习笔记-观察者模式-OOD 封装Listener

    一.概述 childe类中的是关联监听者dad的,若要再增加监听者,会很不方便,且要修改代码.好的方法是封装监听者类,用addListener()方法动态添加监听者 二.代码 1.Test.java ...

  9. Java-马士兵设计模式学习笔记-观察者模式-OOD 封装event

    把小孩醒来时的具体情况封装成事件类 Test.java class WakenUpEvent{ private long time; private String location; private ...

随机推荐

  1. [转载]Eclipse自定义快捷键导出和导入方法

    背景: 以前做C/C++开发,习惯了Visual Studio这个强大的IDE,转到安卓开发后,用到蛋疼的Eclipse,实在不习惯,而且以前总觉得VS不流畅,现在才知道VS很好,才知道什么是真正的& ...

  2. Oracle与Mysql区别简述

    在Mysql中,一个用户下可以创建多个库: 而在Oracle中,Oracle服务器是由两部分组成 数据库实例[理解为对象,看不见的] 数据库[理解为类,看得见的] 一个数据库实例可拥有多个用户,一个用 ...

  3. 06jQuery-06-AJAX

    1.JS的AJAX AJAX,Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求. 如果要让用户留在当前页面中,同时发出新的HTTP请求,就 ...

  4. 理解ES6——Promise

    浏览器的控制台真是个好东西,啥都能干: 这就是Promise,能看出来啥? 1.是个构造函数,可以new实例. 2.自身有一些方法:all.race.reject.resolve... 3.原型上有c ...

  5. DotNetCore跨平台~linux上还原自主nuget包需要注意的问题

    问题的产生的背景 由于我们使用了jenkins进行部署(jenkins~集群分发功能和职责处理),而对于.net core项目来说又是跨平台的,所以对它的项目拉取,包的还原,项目的编译和项目的发布都是 ...

  6. iOS连续dismiss几个ViewController的方法

    原文链接:http://blog.csdn.net/longshihua/article/details/51282388 presentViewController是经常会用到的展现ViewCont ...

  7. PyTorch教程之Training a classifier

    我们已经了解了如何定义神经网络,计算损失并对网络的权重进行更新. 接下来的问题就是: 一.What about data? 通常处理图像.文本.音频或视频数据时,可以使用标准的python包将数据加载 ...

  8. 第4章 同步控制 Synchronization ----死锁(DeadLock)

    Jeffrey Richter 在他所主持的 Win32 Q&A 专栏(Microsoft Systems Journal,1996/07)中曾经提到过,Windows NT 和 Window ...

  9. Springboot 学习笔记 ①

    前言 之前一直在寻找Springboot的学习资料,终于得偿所愿...那么,先给自己定一个小目标 - 能够使用Springboot这套架构来搭建自己的服务. 准备阶段 1. 开发环境 开发环境其实还是 ...

  10. hdu4678 Mine 2013 Multi-University Training Contest 8 博弈题

    Mine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submi ...