Section 1 策略模式 Strategy
模式:经验复用, 软件开发是在不断调整改变的
设计原则 找出应用中需要变化的部分, 把他们从不需要变化的代码中独立(封装)出来;
>分开变化和不变的部分, 代码变化引起的影响小, 系统有弹性
设计原则 针对接口编程, 不是针对实现编程 >利用接口表示行为, 针对超类型(Supertype)编程, 利用多态
设计原则 多用组合Composition, 少用继承
>运行时候动态的改变行为, 使用setter >系统的维护和变化比前期开发需要更多的时间
策略模式 定义算法族, 封装, 让他们可以互换, 让算法的变化独立于使用算法的客户
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//Strategy
class FlyBehavior // You can define more interface like Swim, Quack...
{
public :
virtual void fly() = 0;
};
class Duck
{
public :
void PerformFly() { mpFlyBehavior->fly();}
void setFlyBehavior(FlyBehavior* pFlyBehavior) { mpFlyBehavior = pFlyBehavior;}
protected :
FlyBehavior* mpFlyBehavior;
};
class FlyWithWings : public FlyBehavior
{
public :
virtual void fly(); //implement the way it flys
};
class FlyNotAble : public FlyBehavior
{
public :
virtual void fly();
};
class MallardDuck : public Duck
{
public :
MallardDuck() { mpFlyBehavior = new FlyWithWings();}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//Strategy
void FlyWithWings::fly()
{
cout << "Fly with Wings\n" << endl;
}
void FlyNotAble::fly()
{
cout << "I'm a little chicken\n" << endl;
}
int main() {
//Strategy
MallardDuck duck;
duck.setFlyBehavior( new FlyNotAble());
duck.PerformFly();
return 0;
}
|
>类图 IS-A 是一个(继承 实线+三角 MallardDuck-Duck); HAS-A 有一个(实线+箭头 Duck-FlyBehavior); Implement(虚线+三角 FlyBehavior-FlyWithWings)
Summary
>OO基础 抽象, 封装, 多态, 继承 >OO原则 封装变化, 多组合少继承, 针对接口, 不针对实现编程
>要点 OO基础不足够设计OO系统, 需要设计模式; 良好OO设计 可复用 可扩充 可维护; 模式是历经验证的OO设计经验; 模式是解决方案; 模式是被发现的; 模式和原则, 基于软件的变化;
大多数的模式允许系统局部的改变独立于其他部分; 把变化的部分抽取封装; 模式是共享语言, 利于沟通
Encapsulate, Principles, Strategy, Vocabulary, Recur, Frameworks, Experience, Composition, Observer
---Section1 End---
Section 2 观察者模式 Observer
出版者Subject+订阅者Observer=观察者模式
>观察者模式定义了对象之间一对多的依赖, 当一个对象改变状态时, 所有的依赖者都会收到通知并自动更新.
Subejct是具有状态的对象, Observers使用这些状态, 依赖Subject来告诉他们状态什么时候改变
松耦合 Subject和Observers 改变主题或者观察者其中一方不会影响另一方
设计原则 为了交互对象之间的松耦合设计, 建立有弹性的OO系统
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
//Observer
class IObserver
{
public :
virtual void update( int temp) = 0;
};
class ISubject
{
public :
virtual void registerObservers(IObserver *Ob) = 0;
virtual void removeObservers(IObserver *Ob) = 0;
virtual void notifyObservers() = 0;
};
class IDisplayElement
{
public :
virtual void Display() = 0;
};
typedef list<IObserver*> ObServerList;
class WeatherData : public ISubject
{
public :
WeatherData();
~WeatherData();
virtual void registerObservers(IObserver *Ob);
virtual void removeObservers(IObserver *Ob);
virtual void notifyObservers();
void SetData( int temp);
void DataChanged(){notifyObservers();}
private :
ObServerList mObserverlist;
int mTemp;
};
class ConditionDisplay : public IObserver, public IDisplayElement
{
public :
ConditionDisplay(ISubject *weatherData);
virtual void update( int temp);
virtual void Display();
private :
ISubject* mpWeatherData;
int mTemp;
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
//Observer
WeatherData::WeatherData()
: mTemp(100)
{
}
WeatherData::~WeatherData()
{
mObserverlist.clear();
}
void WeatherData::registerObservers(IObserver *Ob)
{
mObserverlist.push_back(Ob);
}
void WeatherData::removeObservers(IObserver *Ob)
{
ObServerList::iterator iter = mObserverlist.begin();
for (; iter != mObserverlist.end(); iter++)
{
IObserver *Observer = *iter;
if (Observer == Ob)
mObserverlist. remove (Ob);
}
}
void WeatherData::notifyObservers()
{
ObServerList::iterator iter = mObserverlist.begin();
for (; iter != mObserverlist.end(); iter++)
{
IObserver *Ob = *iter;
if (Ob != NULL)
Ob->update(mTemp);
}
}
void WeatherData::SetData( int data)
{
mTemp = data;
DataChanged();
}
ConditionDisplay::ConditionDisplay(ISubject *weatherData)
{
mpWeatherData = weatherData;
mpWeatherData->registerObservers( this );
}
void ConditionDisplay::update( int temp)
{
mTemp = temp;
Display();
}
void ConditionDisplay::Display()
{
cout << "Temperature is changed to " << mTemp << endl;
}
int main() {
//Observer
WeatherData *weatherData = new WeatherData();
ConditionDisplay *conDisplay = new ConditionDisplay(weatherData);
weatherData->SetData(50);
return 0;
}
|
Java内置Observer
>setChanged()用来标记状态的变化, 调用notifyObserver()之前没有调用setChanged(),观察者不会被通知
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import java.util.Observable;
import java.util.Observer;
public class WeatherData extends Observable {
private float temp;
public WeatherData() {}
public void tempChanged(){
setChanged();
notifyObservers();
}
public void setTemp( float temp){
this .temp = temp;
}
// Used for 'PULL'
public float getTemp(){
return this .temp;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
import java.util.Observable;
import java.util.Observer;
import DisplayElement.DisplayElement;
public class ConditionDisplay implements Observer, DisplayElement{
Observable observable;
private float temp;
public ConditionDisplay(Observable observable) {
this .observable = observable;
observable.addObserver( this );
}
public void update(Observable obs, Object arg){
if (obs instanceof WeatherData){
WeatherData weatherData = (WeatherData)obs;
this .temp = weatherData.getTemp();
display();
}
}
public void display(){
System.out.println( "Condition" + temp);
}
/**
* @param args
*/
public static void main(String[] args) {
WeatherData data = new WeatherData();
ConditionDisplay display = new ConditionDisplay(data);
float o = data.getTemp();
float t = 100 ; data.setTemp(t);
if (t - o > 10 ){
data.tempChanged();
}
Object arg = null ;
display.update(data, arg);
}
}
|
1
2
3
4
5
|
package DisplayElement;
public interface DisplayElement {
public void display();
}
|
Summary
>OO原则 为交互对象之间的松耦合设计努力
>OO模式 在对象之间定义一对多的依赖, 当一个对象改变状态, 依赖它的对象都会收到通知, 自动更新
>要点 一对多; 主题/被观察者用一个共同的接口来更新观察者; 松耦合方式结合 LooseCoupling, 被观察者不知道观察者的细节; 可以实现推或拉 push pull; 多个观察者时, 无法依赖特定的通知顺序;
Java有多种观察者实现; Observable的局限; 定制并自己实现Observer; GUI框架大量使用观察者; JavaBeans, RMI;
No Order, Dependent, Interface, Listener-Publisher, Subject-Observer, Loose, Observable
---Section 2 End---