程序设计: 猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。(C#语言)
要求: 1.要有联动性,老鼠和主人的行为是被动的。
2.考虑可扩展性,猫的叫声可能引起其他联动效应。
我么能事件来一步一步来实现: 将要执行的老鼠逃跑,和主人惊醒的行为注册到事件中,猫叫之后引发事件的执行!
1、声明一个委托
namespace ConsoleTest.MouseAndCat
{
public delegate void Delegate();
}
2、因为是由猫叫引发的事件执行,所有事件声明在猫类中
namespace ConsoleTest.MouseAndCat
{
public class Cat
{
public event Delegate Eventhandler;
public void FireAway()
{
if (this.Eventhandler != null)
{
this.Eventhandler();
}
}
}
}
3、下面写(老鼠,主人),对其类实例化时,将要执行的行为注册到事件中
namespace ConsoleTest.MouseAndCat
{
public class Master
{
public Master(Cat cat)
{
cat.Eventhandler += new Delegate(Action);
}
public void Action()
{
Console.WriteLine("主人听见了!");
}
}
public class Mouse
{
public Mouse(Cat cat)
{
cat.Eventhandler += new Delegate(Action);
}
public void Action()
{
Console.WriteLine("老鼠听见了,逃跑!");
}
}
}
4、执行,执行cat的FireAwayAndWakeup方法,内部执行已注册到事件的方法
static void Main(string[] args)
{
Cat cat = new Cat();
Mouse mouse = new Mouse(cat);
Master master = new Master(cat);
cat.FireAway();
}
---------------------------------------------------------------------------------------------
提高一:以上已经实现了,但是考虑到可扩展性,再看第3部分的两个类中,都是在构造函数中注册事件,并且有一个执行的方法,那么如果再扩展其他的功能,比如,邻居听见...等。都需要再写相同的代码,所有我们有必要为观察者(猫叫之后,所引发的对象)提供一个父类或者接口,来统一标准,但是因为观察者都是在构造函数中进行事件的注册,而注册到事件中的方法所做的事件不同(例:老鼠逃跑、主人等),所以我们来创建一个父类(既有接口的功能,也有具体的事件),抽象类,又它来作为观察者的父类
public abstract class Observer
{
public Observer(Cat cat)
{
cat.Eventhandler+=new Delegate(Action);
}
public abstract void Action();
}
那么观察者的类中的也要有相应的变动
public class Master:Observer
{
public Master(Cat cat):base(cat) //执行父类中的构造函数,并且将此派生类中的方法在父类的构造函数中注册到事件中
{ }
public override void Action() //重写抽象类中的抽象方法
{
Console.WriteLine("主人听见了!");
}
}
public class Mouse:Observer
{
public Mouse(Cat cat):base(cat) //执行父类中的构造函数,并且将此派生类中的方法在父类的构造函数中注册到事件中
{}
public override void Action()
{
Console.WriteLine("老鼠听见了,逃跑!");
}
}
这样一来,再对观察者进行相应的扩展的时候也就省去了些许的步骤,如果观察者多了的话,优点之处就会更加明显了。
----------------------------------------------------------------------------------------------------
提高二:我们再对第2部分进行改进,这里是由 猫叫 引发的一系列的行为,但是如果我们之后又想添加 狗叫 引发这些行为的话,那么就需要再重写第2部分的那些代码,本着可扩展的目的,我们为这些引发行为的 引发者(猫、狗) 添加一个父类,父类中去实现引发事件的执行,而其派生类(阿猫、阿狗),只负责去调用其父类中的方法即可..
public abstract class Subject
{
public event Delegate Eventhandler;
public void FireAway()
{
if (this.Eventhandler != null)
{
this.Eventhandler();
}
}
}
那么 引发者 只需要调用父类中的FireAway方法去执行已注册在事件中的方法即可。
public class Cat
{
public void Cry()
{
this.FireAway();
}
}
public class Dog
{
public void Cry()
{
this.FireAway();
}
}
值得注意的是,观察者 的构造函数中的参数类型,要改为引发者的父类:Subject 。因为不止可以将引发的行为(老鼠逃跑、主人醒等)添加到猫引发的事件中,还可以将其添加到狗引发的事件中。
所以整个部分应该为:
namespace ConsoleTest.MouseAndCat
{
public delegate void Delegate();
}
委托
public abstract class Subject
{
public event Delegate Eventhandler;
public void FireAway()
{
if (this.Eventhandler != null)
{
this.Eventhandler();
}
}
}
public class Cat:Subject
{
public void Cry()
{
this.FireAway();
}
} public class Dog:Subject
{
public void Cry()
{
this.FireAway();
}
}
引发者
public abstract class Observer
{
public Observer(Subject sub)
{
sub.Eventhandler += new Delegate(Action);
}
public abstract void Action();
} public class Master:Observer
{
public Master(Subject sub):base(sub)
{ }
public override void Action()
{
Console.WriteLine("主人听见了!");
}
}
public class Mouse:Observer
{
public Mouse(Subject sub): base(sub)
{}
public override void Action()
{
Console.WriteLine("老鼠听见了,逃跑!");
}
}
观察者
static void Main(string[] args)
{
Cat cat = new Cat();
Mouse mouse = new Mouse(cat);
Master master = new Master(cat);
cat.Cry(); Dog dog = new Dog();
Mouse dog_mouse = new Mouse(dog);
Master dog_master = new Master(dog);
dog.Cry(); Console.ReadKey();
}
执行
OK...
程序设计: 猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。(C#语言)的更多相关文章
- Spring 常犯的十大错误,答应我 打死都不要犯好吗?
1. 错误一:太过关注底层 我们正在解决这个常见错误,是因为 “非我所创” 综合症在软件开发领域很是常见.症状包括经常重写一些常见的代码,很多开发人员都有这种症状. 虽然理解特定库的内部结构及其实现, ...
- 2020年度综合大盘点:火爆IT业的7大Java技术,每一项都是大写的“牛逼”!
关注"Java这点事",每天与你分享Java技术.IT资讯 JAVA语言作为历史最为悠久的编程语言,从95年5月开始历经数十年依然盘踞在编程榜前三的位置,与它强大的功能和广泛的运用 ...
- 【偶像大师 白金星光】的【Variable Tone】技术大公开!偶像从哪里看都那么可爱,VA小组谈制作方针
http://game.watch.impress.co.jp/docs/news/1016369.html 自从街机版的运营依赖,今年迎来了[偶像大师]系列的11周年.在CEDEC ...
- 扒一扒各大电商网站的m站都用的什么前端技术输入日志标题
凡客首页使用Swiper和zepto,没有使用jquery , 静态首页+js交互, 资源加载使用 lazyLoad X-AspNet-Version: 4.0.30319 X-AspNetMvc- ...
- C#笔试(程序设计)
1.如何把一个Array复制到ArrayList里,如何把ArrayList复制到Array里? foreach( object o in array )arrayList.Add(o); Array ...
- .NET面试题集锦①(Part一)
一.前言部分 文中的问题及答案多收集整理自网络,不保证100%准确,还望斟酌采纳. 1.面向对象的思想主要包括什么? 答:任何事物都可以理解为对象,其主要特征: 继承.封装.多态.特点:代码好维护,安 ...
- asp.net c# 网上搜集面试题目大全(附答案)
1.String str=new String("a")和String str = "a"有什么区别? String str = "a"; ...
- NET出现频率非常高的笔试题
又到了金三银四的跳槽季,许多朋友又开始跳槽了,这里我简单整理了一些出现频率比较高的.NET笔试题,希望对广大求职者有所帮助. 一..net基础 1. a=10,b=15,请在不使用第三方变量的情况下 ...
- asp.net面试题汇总
1.静态成员和非静态成员的区别? 答: 静态变量使用 static 修饰符进行声明,在类被实例化时创建,通过类进行访问不带有 static 修饰符声明的变量称做非静态变量,在对象被实例化时创建,通过对 ...
随机推荐
- placeholder在不同浏览器下的表现及兼容方法
1.什么是placeholder? placeholder是html5新增的一个属性,当input或者textarea设置了该属性后,该值的内容将作为灰字提示显示在文本框中,当文本框获得焦点(或 ...
- 转载--thinkphp框架的路径问题 - 总结
转自:http://blog.sina.com.cn/s/blog_827ddd950100ulyv.html TP中有不少路径的便捷使用方法,比如模板中使用的__URL__,__ACTION__等, ...
- IIS7 Appcmd.exe 使用
如果您运行的是 64 位 Windows,请从 %windir%\system32\inetsrv 目录而不是 %windir%\syswow64\inetsrv 目录中使用 Appcmd.exe. ...
- Union大小
在一个union类型结构中,所有的成员公用同样的存储空间,其占用的大小为其成员中需要空间最大者: union本身只保留一块地址空间,因为只有一个成员真正存储于该地址, 但这块地址也要满足内存对齐原则. ...
- 前端编码规范(4)—— CSS 和 Sass (SCSS) 规范
CSS and Sass (SCSS) style rules ID and class naming ID和class(类)名总是使用可以反应元素目的和用途的名称,或其他通用名称.代替表象和晦涩难懂 ...
- Apache Storm技术实战之3 -- TridentWordCount
欢迎转载,转载请注明出处. 介绍TridentTopology的使用,重点分析newDRPCStream和stateQuery的实现机理. 使用TridentTopology进行数据处理的时候,经常会 ...
- DS实验题 word
题目: 代码: // // main.cpp // word // // Created by wasdns on 16/11/11. // Copyright © 2016年 wasdns. All ...
- php开源项目
论坛社区:Discuz.PHPWind.ThinkSAAS.phpBB CMS内容管理:DedeCMS.PHPCMS.帝国CMS.齐博CMS.Drupal 企业建站:CmsEasy.KingCMS.P ...
- html 符号大全
░ ▒ ▬ ♦ ◊ ◦ ♠ ♣ ▣ ۰•● ❤ ●•۰► ◄ ▧ ▨ ♨ ◐ ◑ ↔ ↕ ▪ ▫ ☼ ♦ ♧♡♂♀♠♣♥❤☜☞☎☏⊙◎ ☺☻☼▧▨♨◐◑↔↕▪ ▒ ◊◦▣▤▥ ▦▩◘ ◈◇♬♪♩♭♪の ...
- Web Service性能测试方案
目录: 1.web Service简介 2.SoapUI介绍 3.使用SoapUI进行web service性能测试 4.使用LR进行web service性能测试 5.使用JMeter进行web s ...