政策模式
- 類圖
- 定義
- 優缺點
-
- 優點:
- 缺點:
- 設計原則
- 代碼
-
- DUNK類:
- FlyBehavior類:
- QuackBehavior類:
- 測試:
類圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPR9EeZRlT3lFRPpHOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLwMjMyUjMwQTMyETNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
定義
政策模式定義了算法族,分别封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立于使用算法的客戶。
優缺點
優點:
1、 政策模式提供了管理相關的算法族的辦法。政策類的等級結構定義了一個算法或行為族。恰當使用繼承可以把公共的代碼轉移到父類裡面,進而避免重複的代碼。
2、 政策模式提供了可以替換繼承關系的辦法。繼承可以處理多種算法或行為。如果不是用政策模式,那麼使用算法或行為的環境類就可能會有一些子類,每一個子類提供一個不同的算法或行為。但是,這樣一來算法或行為的使用者就和算法或行為本身混在一起。決定使用哪一種算法或采取哪一種行為的邏輯就和算法或行為的邏輯混合在一起,進而不可能再獨立演化。繼承使得動态改變算法或行為變得不可能。
3、 使用政策模式可以避免使用多重條件轉移語句。多重轉移語句不易維護,它把采取哪一種算法或采取哪一種行為的邏輯與算法或行為的邏輯混合在一起,統統列在一個多重轉移語句裡面,比使用繼承的辦法還要原始和落後。
缺點:
1、用戶端必須知道所有的政策類,并自行決定使用哪一個政策類。這就意味着用戶端必須了解這些算法的差別,以便适時選擇恰當的算法類。換言之,政策模式隻适用于用戶端知道所有的算法或行為的情況。
2、 政策模式造成很多的政策類,每個具體政策類都會産生一個新類。有時候可以通過把依賴于環境的狀态儲存到用戶端裡面,而将政策類設計成可共享的,這樣政策類執行個體可以被不同用戶端使用。換言之,可以使用享元模式來減少對象的數量。
設計原則
1、 找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。這個概念很簡單,幾乎是每個設計模式背後的精神所在,所有的模式都提供了一套方法讓系統中的某部分改變不會影響其它部分。(分開變化和不變化的部分)
2、 針對接口程式設計,而不是針對實作程式設計。
3、 多用組合,少用繼承(使用組合建立系統具有很大的彈性,不僅可将算法族封裝成類,更可以在運作時動态地改變行為。)
代碼
DUNK類:
#ifndef DUNK_H
#define DUNK_H
#include "flybehavior.h"
#include "quackbehavior.h"
class Duck
{
public:
Duck();
virtual void diaplay();
void performFly();
void perfomrQuack();
void swim();
void setFlyBehavior(FlyBehavior *fb);
void setQuackBehavior(QuackBehavior *qb);
FlyBehavior *flyBehavior;
QuackBehavior *quackBehavior;
};
class MallardDuck : public Duck
{
public:
MallardDuck();
void diaplay() override;
};
class ModeDuck : public Duck
{
public:
ModeDuck();
void diaplay() override;
};
class DuckCall : public Duck
{
public:
DuckCall();
void diaplay() override;
};
#endif // DUNK_H
#include "duck.h"
Duck::Duck()
{
}
void Duck::diaplay()
{
}
void Duck::performFly()
{
flyBehavior->fly();
}
void Duck::perfomrQuack()
{
quackBehavior->quack();
}
void Duck::swim()
{
qDebug() << "All ducks float, even decoys!";
}
void Duck::setFlyBehavior(FlyBehavior *fb)
{
flyBehavior = fb;
}
void Duck::setQuackBehavior(QuackBehavior *qb)
{
quackBehavior = qb;
}
MallardDuck::MallardDuck()
{
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
void MallardDuck::diaplay()
{
qDebug() << "I'm a real Mallard duck";
}
ModeDuck::ModeDuck()
{
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
void ModeDuck::diaplay()
{
qDebug() << "I'm a model duck";
}
DuckCall::DuckCall()
{
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
void DuckCall::diaplay()
{
qDebug() << "I'm a DuckCall";
}
FlyBehavior類:
#ifndef FLYBEHAVIOR_H
#define FLYBEHAVIOR_H
#include <QDebug>
class FlyBehavior
{
public:
virtual void fly() = 0;
virtual ~FlyBehavior() {};
};
class FlyWithWings : public FlyBehavior
{
public:
void fly() override;
};
class FlyNoWay : public FlyBehavior
{
public:
void fly() override;
};
class FlyRocketPowered : public FlyBehavior
{
public:
void fly() override;
};
#endif // FLYBEHAVIOR_H
#include "flybehavior.h"
void FlyWithWings::fly()
{
qDebug() << "I'm flying!";
}
void FlyNoWay::fly()
{
qDebug() << "I can't fly!";
}
void FlyRocketPowered::fly()
{
qDebug() << "I'm flying with a rocket";
}
QuackBehavior類:
#ifndef QUACKBEHAVIOR_H
#define QUACKBEHAVIOR_H
#include <QDebug>
class QuackBehavior
{
public:
virtual void quack() = 0;
virtual ~QuackBehavior() {};
};
class MuteQuack : public QuackBehavior
{
public:
void quack() override;
};
class Quack : public QuackBehavior
{
public:
void quack() override;
};
class Squeak : public QuackBehavior
{
public:
void quack() override;
};
#endif // QUACKBEHAVIOR_H
#include "quackbehavior.h"
void Quack::quack()
{
qDebug() << "quack";
}
void MuteQuack::quack()
{
qDebug() << "silence";
}
void Squeak::quack()
{
qDebug() << "Squeak";
}
測試:
#include "mainwindow.h"
#include "duck.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
Duck *mallard = new MallardDuck();
mallard->perfomrQuack();
mallard->performFly();
Duck *model = new ModeDuck();
model->performFly();
model->setFlyBehavior(new FlyRocketPowered());
model->performFly();
Duck *duckcall = new DuckCall();
duckcall->perfomrQuack();
duckcall->setQuackBehavior(new Squeak());
duckcall->perfomrQuack();
}
MainWindow::~MainWindow()
{
}