观察者设计模式 [英] Observer Design Pattern

查看:58
本文介绍了观察者设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好!


我正在尝试实现自己的设计模式库。

我已阅读以下关于观察者模式的文档:

1)GoF的设计模式

观察者的经典描述。还通过ChangeManager(Mediator + Singleton)描述实现



2)John Vlissides的模式孵化

描述Observer通过访客设计的实现模式。

3)设计模式由Alan Shalloway和James Trott解释

通过适配器设计模式描述Observer的实现。

4) CUJ的文章:Prying eyes:A Policy-Based Observer I,II by

Andrei Alexandrescu

非常有趣的文章,描述了尝试实施

a基于策略的Observer和几个严重的问题:

a)相互递归(潜在无限循环等...)

b)主动观察者问题(迭代问题)

c)通知订单问题

d)GetState()的返回值问题


我试图结合每种方法的最佳方面。


考虑以下伪代码示例:


class subject

{

public:

virtual void Attach( Observer *)= 0;

virtual void Detach(Observer *)= 0;

virtual void Notify()= 0;


virtual @@@ GetState()= 0; // !!!应该是什么类型

返回???

};


班级观察员

{

public:

虚拟无效更新(主题*)= 0;

};


类MySubject:public Subject

{

public:

void Attach(Observer *)

{

///添加对

}

void Detach(Observer *)

{

/ //删除对

}

void通知()

{

///致电观察员 - >更新(this)为每位观察者提供映射

}


@@@ GetState()

{

///返回特定于MySubject的数据。但是如何???

}

私人:

//主题 - 观察者映射

// MySubject-具体数据

};


class YourSubject:public Subject

{

public:

//沿着类似的行

private:

//主题 - 观察者映射

// YourSubject特定数据< br $>
};


类MyObserver:public Observer ///此类代表MySubject

和YourSubject

{

public:

void Update(Subject * s)

{

/// Only Subject'这里的界面是可用的(不是MySubject

或YourSubject)

///我知道一个不好的解决方案 - 通过dynamic_cast键入切换。

如果TypeOf(s)== MySubject

{

///更新MySubject特定的代表部分

}

else如果TypeOf(s)== YourSubject

{

///更新表示特定部分的表示

}

}

private:

///特定于MyObserver的数据(例如用于主题的GUI小部件

表示)

};

问题在于主题界面不佳。

对象对MySubject的私人数据一无所知。


我不明白为什么GoF在主题中包含GetState方法

接口。

GetState()的返回值取决于具体的子类

主题,即

类ConcreteSubject:Subject

{

public:

ReturnValue< ConcreteSubject> GetState();

...

};


主要问题:

如何避免在ConcreteObserver :: Update(主题*)中进行类型切换?


谢谢!


PS

对不起对于我的英语:)

解决方案



Krivenok Dmitry写道:

大家好!

我正在尝试实现自己的设计模式库。
我已经阅读了以下关于观察者模式的文档:
1)GoF的设计模式
观察者的经典描述。还通过ChangeManager(Mediator + Singleton)描述实现
2)John Vlissides的模式孵化
通过访问者设计模式描述观察者的实现。
3)设计模式由Alan Shalloway和James Trott
通过适配器设计模式描述Observer的实现。
4)CUJ的文章:Prying eyes:一个基于策略的观察者I,II。作者:Andrei Alexandrescu
非常有趣的文章,描述了尝试实施基于策略的观察者和几个严重的问题:
a)相互递归(潜在的无限循环等等。 。)
b)主动观察者问题(迭代问题)
c)通知顺序问题
d)GetState()的返回值问题

我正在尝试结合每种方法的最佳方面。

考虑以下伪代码示例:

类主题
{
公开:
虚拟void Attach(Observer *)= 0;
virtual void Detach(Observer *)= 0;
virtual void Notify()= 0;

virtual @@@ GetState() = 0; // !!!应该返回什么类型
返回???
};

班级观察员
公开:
虚拟无效更新(主题*) = 0;
};

类MySubject:public主题
{
公开:
void Attach(Observer *)
{
///添加对
}
void Detach(Observer *)
{
///删除对
}
void Notify()
{
///为映射中的每个观察者调用observer->更新(this)

@@@ GetState()
{
///返回特定于MySubject的数据。但是如何???
}
私人:
//主题 - 观察者映射
// MySubject特定数据
};

class YourSubject:public Subject
{
public:
//沿着类似的方向
private:
// Subject-Observer mapping
// YourSubject-specific数据
};

类MyObserver:public Observer ///这个类代表MySubject
和YourSubject
{
公开:
void更新(主题* s)
///这里只提供主题的界面(不是MySubject
或YourSubject)
///我知道一个不好的解决方案 - 类型通过dynamic_cast切换。
如果TypeOf(s)== MySubject
{
///更新MySubject特定的表示部分
}
如果是TypeOf(s) == YourSubject
///更新表示特定部分的表示
}
}
私人:
/// MyObserver-具体数据(例如用于主题的GUI小部件
表示)
};

问题在于主题界面不佳。
主题对MySubject一无所知''私人数据。

我不明白为什么GoF在Subject'的
界面中包含GetState方法。
GetState()的返回值依赖于
主题的具体子类,即
类ConcreteSubject:Subject
公共:
ReturnValue< ConcreteSubject> GetState();
...
};

主要问题:
如何避免在ConcreteObserver :: Update(主题*)中进行类型切换?

谢谢!

PS
对不起我的英文:)




也许你应该尽量避免阅读许多设计书籍。你可以开始伪造你在GoF书中读到的所有内容(除非你有兴趣让你作为程序员的生活变得更难以及你的代码更多

复杂)


bo ****** *@yahoo.com 写道:

Krivenok Dmitry写道:

大家好!

我正在尝试实现自己的设计模式库。
我已经阅读了以下关于观察者模式的文档:
1)GoF的设计模式
观察者的经典描述。还通过ChangeManager(Mediator + Singleton)描述实现
2)John Vlissides的模式孵化
通过访问者设计模式描述观察者的实现。
3)设计模式由Alan Shalloway和James Trott
通过适配器设计模式描述Observer的实现。
4)CUJ的文章:Prying eyes:一个基于策略的观察者I,II。作者:Andrei Alexandrescu
非常有趣的文章,描述了尝试实施基于策略的观察者和几个严重的问题:
a)相互递归(潜在的无限循环等等。 。)
b)主动观察者问题(迭代问题)
c)通知顺序问题
d)GetState()的返回值问题

我正在尝试结合每种方法的最佳方面。

考虑以下伪代码示例:


[剪切代码]

主要问题:
如何避免在ConcreteObserver :: Update(主题*)中进行类型切换?



也许你应该尽量避免阅读许多设计书籍。你可以首先伪造你在GoF书中读到的所有东西(除非你有兴趣让你的生活变得更难,你的代码更加复杂)




也许你可以用一些特定的实例来支持它吗?


Jeff Flinn


Krivenok Dmitry写道:

大家好!

我正在尝试实现自己的设计模式库。


你不可能做到这一点。设计模式比简单的代码重用更高级别b $ b。那说...


经典的拉模型可以像这样实现:


class Observer

{

public:

virtual~Observer (){}

virtual void update()= 0;

};


class subject

{

std :: set<观察者*>观察员;

public:

void attach(Observer * o){

observers.insert(o);

}


void detach(Observer * o){

observers.erase(o);

}


void notify(){

for_each(observers.begin(),observers.end(),

mem_fun(& Observer ::更新));

}

};

class MySubject:public Subject

{

int state;

public:

int getState()const {return state; } $ / $
void setState(int value){state = value;通知(); }

};


类MyObserver:public Observer

{

MyObserver(const MyObserver& );

MyObserver& operator =(const MyObserver&);


MySubject * subject;


public:

MyObserver(MySubject * subject_):subject(subject_){

subject-> attach(this);

}


~MyObserver() {

subject-> detach(this);

}


void update(){

//使用subject->做一些事情getState();

}

};


然而,我有找到了推模型更有用:


模板< typename Observer>

class subject {

std :: set<观察者*>观察员;


public:

void attach(Observer * o){

observers.insert(o);

}


void detach(Observer * o){

observers.erase(o);

}


模板< typename ConcreteSubject>

void notify(const ConcreteSubject * cs,void(Observer :: * fn)(const

ConcreteSubject *)){

std :: set< Observer *> :: iterator it = observers.begin();

while(it!= observers.end()){

Observer * ob(* it ++) ;

(ob-> * fn)(cs);

}

}

};

我不明白为什么GoF在Subject'的
界面中包含GetState方法。


他们这样做是因为他们正在查看SmallTalk的例子,这些例子是
并没有很好地翻译成C ++

主要问题:
如何避免在ConcreteObserver :: Update(主题*)中进行类型切换?




如上所示。


Hello All!

I am trying to implement my own Design Patterns Library.
I have read the following documentation about Observer Pattern:
1) Design Patterns by GoF
Classic description of Observer. Also describes implementation
via ChangeManager (Mediator + Singleton)
2) Pattern hatching by John Vlissides
Describes Observer''s implementation via Visitor Design Pattern.
3) Design Patterns Explained by Alan Shalloway and James Trott
Describes Observer''s implementation via Adaptor Design Pattern.
4) CUJ''s article : "Prying eyes : A Policy-Based Observer I,II" by
Andrei Alexandrescu
Very interesting articles, which describes attempt to implement
a policy-based Observer and several serious problems:
a) Mutual recursion (potential infinite loops, etc...)
b) Active observers problem (iteration problem)
c) Notification order problem
d) GetState()''s return value problem

I am trying to combine best aspects of each approach.

Consider the following pseudo-code example:

class Subject
{
public:
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;

virtual @@@ GetState() = 0; // !!! What type should be
returned???
};

class Observer
{
public:
virtual void Update(Subject*) = 0;
};

class MySubject : public Subject
{
public:
void Attach(Observer*)
{
/// Add pair
}
void Detach(Observer*)
{
/// Delete pair
}
void Notify()
{
/// Call observer->Update(this) for each observer in mapping
}

@@@ GetState()
{
/// Return MySubject-specific data. BUT HOW???
}
private:
// Subject-Observer mapping
// MySubject-specific data
};

class YourSubject : public Subject
{
public:
// Along similar lines
private:
// Subject-Observer mapping
// YourSubject-specific data
};

class MyObserver : public Observer /// This class represents MySubject
and YourSubject
{
public:
void Update(Subject* s)
{
/// Only Subject''s interface is available here (not MySubject
or YourSubject)
/// I know one bad solution - type switch via dynamic_cast.
if TypeOf(s) == MySubject
{
/// Update MySubject-specific part of representation
}
else if TypeOf(s) == YourSubject
{
/// Update YourSubject-specific part of representation
}
}
private:
/// MyObserver-specific data (e.g. GUI widgets for subjects
representation)
};
The problem lies in poor Subject''s interface.
Subject doesn''t know anything about MySubject''s private data.

I don''t understand why GoF includes GetState method in Subject''s
interface.
Type of GetState()''s return value depends up concrete subclass of
Subject, i.e.
class ConcreteSubject : Subject
{
public:
ReturnValue<ConcreteSubject> GetState();
...
};

Main question:
How to avoid type switching in ConcreteObserver::Update(Subject* s)?

Thanks!

P.S.
Sorry for my english :)

解决方案


Krivenok Dmitry wrote:

Hello All!

I am trying to implement my own Design Patterns Library.
I have read the following documentation about Observer Pattern:
1) Design Patterns by GoF
Classic description of Observer. Also describes implementation
via ChangeManager (Mediator + Singleton)
2) Pattern hatching by John Vlissides
Describes Observer''s implementation via Visitor Design Pattern.
3) Design Patterns Explained by Alan Shalloway and James Trott
Describes Observer''s implementation via Adaptor Design Pattern.
4) CUJ''s article : "Prying eyes : A Policy-Based Observer I,II" by
Andrei Alexandrescu
Very interesting articles, which describes attempt to implement
a policy-based Observer and several serious problems:
a) Mutual recursion (potential infinite loops, etc...)
b) Active observers problem (iteration problem)
c) Notification order problem
d) GetState()''s return value problem

I am trying to combine best aspects of each approach.

Consider the following pseudo-code example:

class Subject
{
public:
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;

virtual @@@ GetState() = 0; // !!! What type should be
returned???
};

class Observer
{
public:
virtual void Update(Subject*) = 0;
};

class MySubject : public Subject
{
public:
void Attach(Observer*)
{
/// Add pair
}
void Detach(Observer*)
{
/// Delete pair
}
void Notify()
{
/// Call observer->Update(this) for each observer in mapping
}

@@@ GetState()
{
/// Return MySubject-specific data. BUT HOW???
}
private:
// Subject-Observer mapping
// MySubject-specific data
};

class YourSubject : public Subject
{
public:
// Along similar lines
private:
// Subject-Observer mapping
// YourSubject-specific data
};

class MyObserver : public Observer /// This class represents MySubject
and YourSubject
{
public:
void Update(Subject* s)
{
/// Only Subject''s interface is available here (not MySubject
or YourSubject)
/// I know one bad solution - type switch via dynamic_cast.
if TypeOf(s) == MySubject
{
/// Update MySubject-specific part of representation
}
else if TypeOf(s) == YourSubject
{
/// Update YourSubject-specific part of representation
}
}
private:
/// MyObserver-specific data (e.g. GUI widgets for subjects
representation)
};
The problem lies in poor Subject''s interface.
Subject doesn''t know anything about MySubject''s private data.

I don''t understand why GoF includes GetState method in Subject''s
interface.
Type of GetState()''s return value depends up concrete subclass of
Subject, i.e.
class ConcreteSubject : Subject
{
public:
ReturnValue<ConcreteSubject> GetState();
...
};

Main question:
How to avoid type switching in ConcreteObserver::Update(Subject* s)?

Thanks!

P.S.
Sorry for my english :)



Maybe you should try to avoid reading to many design books. You can
start by forgeting everything you read in the GoF book (unless you
interested in making your life as programmer harder and your code more
complicated)


bo*******@yahoo.com wrote:

Krivenok Dmitry wrote:

Hello All!

I am trying to implement my own Design Patterns Library.
I have read the following documentation about Observer Pattern:
1) Design Patterns by GoF
Classic description of Observer. Also describes implementation
via ChangeManager (Mediator + Singleton)
2) Pattern hatching by John Vlissides
Describes Observer''s implementation via Visitor Design Pattern.
3) Design Patterns Explained by Alan Shalloway and James Trott
Describes Observer''s implementation via Adaptor Design Pattern.
4) CUJ''s article : "Prying eyes : A Policy-Based Observer I,II" by
Andrei Alexandrescu
Very interesting articles, which describes attempt to implement
a policy-based Observer and several serious problems:
a) Mutual recursion (potential infinite loops, etc...)
b) Active observers problem (iteration problem)
c) Notification order problem
d) GetState()''s return value problem

I am trying to combine best aspects of each approach.

Consider the following pseudo-code example:
[snipped code]
Main question:
How to avoid type switching in ConcreteObserver::Update(Subject* s)?



Maybe you should try to avoid reading to many design books. You can
start by forgeting everything you read in the GoF book (unless you
interested in making your life as programmer harder and your code
more complicated)



Maybe you could back that up with some specific instances?

Jeff Flinn


Krivenok Dmitry wrote:

Hello All!

I am trying to implement my own Design Patterns Library.
You can''t do that in general. Design Patterns are at a level higher
than simple code reuse. That said...

The classic "pull model" can be implemented like this:

class Observer
{
public:
virtual ~Observer() { }
virtual void update() = 0;
};

class Subject
{
std::set< Observer* > observers;
public:
void attach( Observer* o ) {
observers.insert( o );
}

void detach( Observer* o ) {
observers.erase( o );
}

void notify() {
for_each( observers.begin(), observers.end(),
mem_fun( &Observer::update ) );
}
};
class MySubject : public Subject
{
int state;
public:
int getState() const { return state; }
void setState( int value ) { state = value; notify(); }
};

class MyObserver : public Observer
{
MyObserver( const MyObserver& );
MyObserver& operator=( const MyObserver& );

MySubject* subject;

public:
MyObserver( MySubject* subject_ ): subject( subject_ ) {
subject->attach( this );
}

~MyObserver() {
subject->detach( this );
}

void update() {
// do something with subject->getState();
}
};

However, I have found the "push model" to be much more useful:

template < typename Observer >
class Subject {
std::set< Observer* > observers;

public:
void attach( Observer* o ) {
observers.insert( o );
}

void detach( Observer* o ) {
observers.erase( o );
}

template < typename ConcreteSubject >
void notify( const ConcreteSubject* cs, void (Observer::*fn)( const
ConcreteSubject* ) ) {
std::set< Observer* >::iterator it = observers.begin();
while ( it != observers.end() ) {
Observer* ob( *it++ );
(ob->*fn)( cs );
}
}
};
I don''t understand why GoF includes GetState method in Subject''s
interface.
They did that because they were looking at SmallTalk examples which
didn''t translate well to C++
Main question:
How to avoid type switching in ConcreteObserver::Update(Subject* s)?



As I showed above.


这篇关于观察者设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆