当前位置: 代码迷 >> 综合 >> Head First 设计模式 Design Pattern 1-2 Strategy, Observer
  详细解决方案

Head First 设计模式 Design Pattern 1-2 Strategy, Observer

热度:2   发布时间:2023-12-20 11:26:21.0

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;
}
MVC-Model View Controller

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---

  相关解决方案