定义:
观察者模式
(ObserverPattern)
,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
类型:对象行为型模式
概述:
观察者模式也是比较难以理解,单看类图,会发现观察者模式与中介模式非常相似。如果不真正理解他们二者之间的区别,是难以真正理解观察者模式的。如果不理解观察者模式,更奢谈运用观察者模式了。
中介模式主要是解决一系列交互对象的耦合的问题,而提出了中介类。几个以前交互的对象现在统一通过中介类来完成交流。而观察者模式侧重的是一对多的通知的功能,即当发生某件事时,主题对象将向所有注册过的观察者对象发出通知消息。
中介模式侧重通过中介类来完成交流;而观察者模式侧重于一对多的通知。中介模式不需要知道具体的中介类的对象,需要交互的对象只需要知道一个通知中介对象的接口即可,具体是哪个中介来完成交互对象告诉的任务,交互对象不需要知道。但是交互对象必须知道有哪些交互对象,这样才能把对象A需要对象B做的事想办法通知到对象B。
观察者模式则,Subject对象不需要知道具体的观察者是谁,它只需要知道观察者的通知接口,就可以将消息通知到观察者。至于具体有哪些消息,则需要观察者自己去具体的Subject那里查看。
这里举一个例子,某电商有大促销,通过邮件发送促销消息给消费者。但是如果消费者想了解有哪些具体的促销信息,则即需要亲自去电商网站查看有哪些具体的促销信息。
类图:
参与者:
- Vender,提供接口来完成对观察者的注册通知。
- YiXun,具体的电商,为消费者提供所需要查看具体信息。
- Observer,提供Update接口。
- CustomerA、CustomerB,具体的观察者,当有更新时去查看电商中自己喜欢的产品。
示例代码:
using
System
;
using
System
.
Collections
.
Generic
;
using
System
.
Text
;
namespace
Design20
{
abstract
class
Vender
{
private
IList
<
Observer
>
observers
=
new
List
<
Observer
>
(
)
;
// 观察者注册
public
void
Register
(
Observer
observer
)
{
observers
.
Add
(
observer
)
;
}
//通知
public
void
Notify
(
)
{
foreach
(
Observer
o
in
observers
)
{
o
.
Update
(
)
;
}
}
}
//具体通知者
class
YiXun
:
Vender
{
private
string
subjecPhone
;
private
string
subjecLaptop
;
//具体通知者状态
public
string
SubjecPhone
{
get
{
return
subjecPhone
;
}
set
{
subjecPhone
=
value
;
}
}
//具体通知者状态
public
string
SubjecLaptop
{
get
{
return
subjecLaptop
;
}
set
{
subjecLaptop
=
value
;
}
}
}
abstract
class
Observer
{
public
abstract
void
Update
(
)
;
}
class
CustomerA
:
Observer
{
private
YiXun
subject
;
public
CustomerA
(
YiXun
subject
)
{
this
.
subject
=
subject
;
}
//更新
public
override
void
Update
(
)
{
Console
.
WriteLine
(
"
消费者A查看到的是{0}
"
,
this
.
subject
.
SubjecPhone
)
;
}
public
YiXun
Subject
{
get
{
return
subject
;
}
set
{
subject
=
value
;
}
}
}
class
CustomerB
:
Observer
{
private
YiXun
subject
;
public
CustomerB
(
YiXun
subject
)
{
this
.
subject
=
subject
;
}
//更新
public
override
void
Update
(
)
{
Console
.
WriteLine
(
"
消费者B查看到的是{0}
"
,
this
.
subject
.
SubjecLaptop
)
;
}
public
YiXun
Subject
{
get
{
return
subject
;
}
set
{
subject
=
value
;
}
}
}
class
Program
{
static
void
Main
(
string
[
]
args
)
{
YiXun
subject
=
new
YiXun
(
)
;
subject
.
Register
(
new
CustomerA
(
subject
))
;
subject
.
Register
(
new
CustomerB
(
subject
))
;
// 来了新手机和新笔记本电脑,然后通知到所有注册的消费者.
// 然后消费者去查看自己感兴趣的产品有哪些.
subject
.
SubjecPhone
=
"
IPhone5s
"
;
subject
.
SubjecLaptop
=
"
ThinkPad
"
;
subject
.
Notify
(
)
;
Console
.
Read
(
)
;
}
}
}
适用性:
- 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类。
优缺点:
- 优点,降低命令发起者与命令接受者之间的耦合,发布者通过接口通知所有观察者。
- 缺点,具体的观察者依赖了具体的发布者。
参考资料:
- 《设计模式——可复用面向对象软件基础》
- 《大话设计模式》