题目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. 201521123067《Java程序设计》第1周学习总结

    1.本周学习总结 在本周的java学习中,我知道了java的发展历程,JDK和JRE以及JVM的区别与联系,并学习了如何安装Eclipse和搭建java的环境,编写出了第一个java程序,明白了jav ...

  2. 201521123031 《Java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  3. Junit4学习(三)Junit运行流程

    一,验证Junit测试方法的流程 1,在test/com.duo.util右键,新建测试类 2,生成后的代码: package com.duo.util; import static org.juni ...

  4. mysql不能插入中文数据

    上次遇到的是向mysql插入中文数据,中文数据乱码了.这次直接就不能插入中文数据了!!!! 参考博文:http://blog.csdn.net/generalyy0/article/details/7 ...

  5. HttpServletRequest获取URL、URI

    从Request对象中可以获取各种路径信息,以下例子: 假设请求的页面是index.jsp,项目是WebDemo,则在index.jsp中获取有关request对象的各种路径信息如下 import j ...

  6. Spring02-AOP

    1,动态代理,指的是通过一个代理对象创建需要的业务对象,然后在这个代理对象中统一进行各种操作. 步骤: 1)写一个类实现InvocationHandler接口: 2)创建要代理的对象 2,创建一个简单 ...

  7. python import xxx 与 from xxx import xx 模块引入的区别

    有如下脚本script1.py: A='aaaa'B='bbbb'C='cccc'print A,B,C 1.命令行交互模式下使用import 导入方式1: >>>import sc ...

  8. virtualbox修改主机名

    virtualbox修改主机名 /etc/hostname /etc/hosts

  9. (转)Unity3D中移动物体位置的几种方法

    1. 简介 在unity3d中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position. 2. 通过Transform组件移动物体 Transform 组件用于描述物体在 ...

  10. Codeforce 854 A. Fraction

    A. Fraction time limit per test 1 second memory limit per test 512 megabytes input standard input ou ...