题目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. Calico 的默认连通性 - 每天5分钟玩转 Docker 容器技术(69)

    前面我们完成了 Calico 网络的部署并运行了容器,今天将讨论 Calico 的连通性. 测试一下 bbox1 与 bbox2 的连通性: ping 成功,数据包流向如下图所示. ① 根据 bbox ...

  2. Java SVN管理工具的使用

    1.svn环境搭建 在应用myEclips 8.5做项目时,svn会成为团队项目的一个非常好的工具,苦苦在网上寻求了一下午,终于整合好了这个环境,在这里简单介绍下,希望能为刚开始用svn的朋友一点点帮 ...

  3. openfire:基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

    基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件 上一篇文章介绍到怎么在自己的Java环境中搭建openfire插件开发的环境,同时介绍到怎样一步步简单的开发openfir ...

  4. POJ 3190 Stall Reservations (优先队列)C++

    Stall Reservations Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7646   Accepted: 271 ...

  5. java.lang.IllegalArgumentException: Result Maps collection already contains value for

    如果在SSM整合的时候出现以下的错误: 留意一下是不是既在Mybatis配置文件中加载了映射文件,又在Spring配置文件中使用扫描式去加载映射文件了.两者是不能够重合使用的! Caused by: ...

  6. java.sql.Exception:setString 只能处理少于 32766 个字符的字符串

    java.sql.Exception:setString 只能处理少于 32766 个字符的字符串 解决方式是 : 升级ojdbc的版本,   将原来的 ojdbc14_10.2.0.2.0.jar ...

  7. 将eclipse左边目录结构改为 树形结构

    认情况下Eclipse的显示内容如下: 这种视图我们看起来不太方便,于是我们需要改变一下它的显示结构,我们点击一下下图中蓝色圆圈圈住的图标 在弹出的框中把鼠标放到"package prese ...

  8. JDFS:一款分布式文件管理系统,第四篇(流式云存储续篇)

    一 前言 本篇博客是JDFS系列博客的第四篇,从最初简单的上传.下载,到后来加入分布式功能,背后经历了大量的调试,尤其当实验的虚拟计算结点数目增加后,一些潜在的隐藏很深的bug就陆续爆发.在此之前笔者 ...

  9. anular2 表单包含多个组件并验证提交

    angular2表单最常用的方法就是在input或者textarea里直接添加formControlName或者formControlGroup进行数据双向绑定并验证. <form [formG ...

  10. B树、B+树、B*树

    二叉搜索树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如 ...