1. 单例模式(Singleton)
我的故事:最近我在使用一个赚取积分的软件,只要用申请的帐号登录后,就可以获得积分,足够的积分就可以在网上直接兑换成小玩具,巧克力和糖果。于是我申请了很多帐号,并让它们同时登录,我想这是个不错的主意,因为多个帐号同时登录就可同时赚取积分获得更多的糖果了,哈哈哈。。。。直到有一天。。。。。。。。。
思路:由于一个类只能有一个实例,所以不能直接用构造函数来生成实例。我们想到的是向外提供一个公有方法,在该方法中判断实例的存在,决定是否生成实例。怎么访问这个方法呢?让我想想。。。。嗯。。。我们不是可以把它声明为static方法吗,这样就可以直接通过类来访问了。
方法:(1) 要使构造函数不被用来生成实例,必须将它的public访问控制改成private或者protected。
(2) 公有方法的作用:判断是否存在一个实例,如果存在则返回该实例,否则创建一个实例。因些它返回类的实例。由于被调用前没有形成实例,必须把该方法声明为static类型的,通过类名来调用。
(3) 类中必须有一个保存该实例的类变量。同理声明为static类型,使它和实例脱勾。
实例列举:你可以打开多个记事本,但不管你按多少次的Ctrl+Alt+Del,你也只能打开一个windows任务管理器
using System.Collections;
class TaskManageWindow
{
private static TaskManageWindow instance; // (3) 声明一个私有的静态变量,保存类的实例
protected TaskManageWindow() // (1) 限制构造函数访问权限,也可声明为private
{
}
public static TaskManageWindow GetInstance() // (2) 公有的静态方法决定是否创建类实例
{
if (instance == null) //还没有任何实例则创建一个实例
{
instance = new TaskManageWindow();
}
return instance; //已存在实例则返回该实例
}
}
class Client
{
static void Main(string[] args)
{
TaskManageWindow w1 = TaskManageWindow.GetInstance();
TaskManageWindow w2 = TaskManageWindow.GetInstance();
TaskManageWindow w3 = TaskManageWindow.GetInstance();
// 判断是否为同一个实例
if ((w1 == w2) && (w2 == w3))
Console.WriteLine("The same window!");
Console.Read();
}
}
输出:
The same window!
注意:以上实例只用于单线程环境。对于多线程环境,必须加锁处理或信号量处理。
2. 观察者模式(Observer)
现实生活中的例子:多个用户订阅了小李在Youtube上的视频,当有新的视频上传,系统自动发邮件通知各个订阅者。
思路:该模式讲述的是一种多对一的依赖关系,当一件事物发生变化,依赖于该事物的其它所有事物应该作出反应。主题发生变化,则通知相关的订阅者。这样,主题必须维护一群订阅者,在主题类中用ArrayList来存储。通知这个动作针对的是每一个订阅者,用foreach可以办到,且该动作是因主题变化而触发的。订阅者除了对主题的变化表示响应外完全可以不做其它事情。
例子实现:
using System.Collections;
abstract class Subject
{
private string name;
ArrayList subscriber = new ArrayList(); //该主题维护的一系列订阅者
public Subject(string name)
{
this.name = name;
}
public void Attach(VideoSubscriber vsub) //加入订阅者
{
subscriber.Add(vsub);
}
public void Detach(VideoSubscriber vsub) //删除订阅者
{
subscriber.Remove(vsub);
}
public void NotifySubscriber() //一一通知订阅者(调用订阅者列表中订阅者的响应函数 )
{
foreach (VideoSubscriber sub in subscriber)
sub.Response();
}
public void AddNewVideo() //主题发生变化
{
NotifySubscriber();
}
}
class Releaser : Subject //具体的主题,本例中即发布者
{
public Releaser(string name)
: base(name)
{ }
}
interface ISubscriber //抽象的订阅者
{
void Response();
}
class VideoSubscriber : ISubscriber //具体的订阅者,视频订阅者
{
private string name;
public VideoSubscriber(string name)
{
this.name = name;
}
public void Response() //当发布者发生变化时,订阅者需要作出的反应
{
Console.WriteLine("{0}收到视频更新消息!",name);
}
}
class Client
{
static void Main(string[] args)
{
Releaser rls = new Releaser("小李");
VideoSubscriber subscriber1 = new VideoSubscriber("subscriber1");
VideoSubscriber subscriber2 = new VideoSubscriber("subscriber2");
VideoSubscriber subscriber3 = new VideoSubscriber("subscriber3");
//将各订阅者加入到发布者管理的订阅者列表中,也称为“注册”。
rls.Attach(subscriber1);
rls.Attach(subscriber2);
rls.Attach(subscriber3);
rls.AddNewVideo();
//将一个订阅者从发布者管理的订阅者列表中删除
rls.Detach(subscriber3);
rls.AddNewVideo();
Console.Read();
}
}
输出:
subscriber1收到视频更新消息!
subscriber2收到视频更新消息!
subscriber3收到视频更新消息!
subscriber1收到视频更新消息!
subscriber2收到视频更新消息!
当我们掌握了该模式中的角色和要素,换换类名和方法名,改写一下方法中的内容,就能轻而易举地模仿生活中的观察者模式。如:班上要搞活动,班长将通知班上的各个同学作些准备;将我的宝马开到A宾馆,负责看车的工作人员说,一有情况就通知你。每个房间都装上了烟雾传感器,意外情况时,控制中心的警报器发出警报。

浙公网安备 33010602011771号