1. 程式人生 > >Head First設計模式——策略模式

Head First設計模式——策略模式

Head First設計模式》是一本介紹設計模式的書籍,書中的設計模式主要是用Java語言進行實現,由於本人對C++比較熟悉,因此在閱讀這本書籍時,儘自己所能,用C++重新去實現書中所涉及到的設計模式。若有錯誤或需要進一步討論之處,望閱覽者不吝賜教!

策略模式——定義了演算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變換獨立於使用演算法的客戶。

需求:一家公司需要設計一款模擬鴨子游戲的電子軟體。遊戲中會出現各種鴨子,比如橡皮鴨、誘餌鴨、鴨等,這些鴨子會有不同的行為,比如有的會叫、有的不會叫、有的會飛、有的不會飛等。為了適應不同的鴨子物件和鴨子行為,可以用策略模式進行整個框架的構建。

1、設計一個鴨子類Duck,一個飛行行為介面類(C++裡面沒有介面的的說法,這裡套用Java裡的說法,更容易理解)FlyBehavior,一個叫聲介面類QuackBehavior,這是第一個設計模式,所以沒有考慮周全,將這三個類放到了一個.h檔案裡;一般而言,應該分開為三個.h檔案。Duck.h、Duck.cpp檔案具體程式碼如下:

#pragma once
#include<iostream>
using namespace std;

class FlyBehavior;
class QuackBehavior;

class CDuck
{
public:
	CDuck();
	~CDuck();

	virtual void display() {}
	virtual void performFly();
	virtual void performQuack();

	void setFlyBehavior(FlyBehavior *fb);
	void setQuackBehavior(QuackBehavior *qb);
	void swim();

protected:
	FlyBehavior* flyBehavior;
	QuackBehavior* quackBehavior;
};

class FlyBehavior
{
public:
	FlyBehavior() {}
	~FlyBehavior() {}

	virtual void fly() {}
private:

};

class QuackBehavior
{
public:
	QuackBehavior() {}
	~QuackBehavior() {}

	virtual void quack(){}
private:

};

class FlyWithWings:public FlyBehavior      //第一個具體飛行行為類
{
public:
	FlyWithWings() {}
	~FlyWithWings() {}
	void fly()
	{
		cout << "I'm flying!!" << endl;
	}
private:

};

class FlyNoWay :public FlyBehavior   //第二個具體飛行行為類
{
public:
	FlyNoWay() {}
	~FlyNoWay() {}
	void fly()
	{
		cout << "I can't fly!!" << endl;
	}
private:

};

class FlyRocketPowered:public FlyBehavior  //第三個具體飛行行為類
{
public:
	FlyRocketPowered(){}
	~FlyRocketPowered(){}

	void fly()
	{
		cout << "I'm flying with rocket!!" << endl;
	}

private:

};

class Quack:public QuackBehavior      //第一個具體叫聲類
{
public:
	Quack() {}
	~Quack() {}

	void quack()
	{
		cout << "Quack" << endl;
	}
private:

};

class MuteQuack :public QuackBehavior  //第二個具體叫聲類
{
public:
	MuteQuack() {}
	~MuteQuack() {}

	void quack()
	{
		cout << "<< Silence >>" << endl;
	}
private:

};

class Squeak :public QuackBehavior  //第三個具體叫聲類
{
public:
	Squeak() {}
	~Squeak() {}

	void quack()
	{
		cout << "Squeak" << endl;
	}
private:

};



#include "Duck.h"

CDuck::CDuck()
{
}

CDuck::~CDuck()
{
}

void CDuck::performFly()
{
	flyBehavior->fly();
}

void CDuck::performQuack()
{
	quackBehavior->quack();
}

void CDuck::swim()
{
	cout << "All ducks float,even decoys!!" << endl;
}

void CDuck::setFlyBehavior(FlyBehavior* fb)
{
	flyBehavior = fb;
}

void CDuck::setQuackBehavior(QuackBehavior *qb)
{
	quackBehavior = qb;
}

2、建立兩個具體鴨子類:MallardDuck、ModelDuck,MallardDuck.h、MallardDuck.cpp、ModelDuck.h、ModelDuck.cpp檔案具體程式碼如下:

#pragma once
#include "Duck.h"
class CMallardDuck :public CDuck
{
public:
	CMallardDuck();
	~CMallardDuck();

	void display();
};
#include "MallardDuck.h"

CMallardDuck::CMallardDuck()
{
	quackBehavior = new Quack();
	flyBehavior = new FlyWithWings();
}

CMallardDuck::~CMallardDuck()
{

}

void CMallardDuck::display()
{
	cout << "I'm a real Mallard duck!!" << endl;
}
#pragma once
#include "Duck.h"
class CModelDuck :
	public CDuck
{
public:
	CModelDuck();
	~CModelDuck();
	void display();
};

#include "ModelDuck.h"



CModelDuck::CModelDuck()
{
	flyBehavior = new FlyNoWay();
	quackBehavior = new Quack();
}


CModelDuck::~CModelDuck()
{
}

void CModelDuck::display()
{
	cout << "I'm a model duck!!" << endl;
}

3、測試程式碼和結果如下:

/*
策略模式:定義了演算法族,分別封裝起來,讓它們之間可以相互替換,此模式讓
演算法的變化獨立於使用演算法的客戶
*/
#include "Duck.h"
#include "MallardDuck.h"
#include "ModelDuck.h"

int main()
{
	CDuck* mallard = new CMallardDuck();
	mallard->performFly();
	mallard->performQuack();

	CDuck* model = new CModelDuck();
	model->performFly();
	model->setFlyBehavior(new FlyRocketPowered());
	model->performFly();

	delete mallard;
	delete model;
	return 0;
}

在講述策略模式時,書中涉及到了三個OO原則:

1、封裝變化,即將框架中易於變化的部分抽象出來,形成獨立的類;

2、多用組合,少用繼承,即類與類之間儘量處於合作關係,而不是依賴關係;

3、針對介面程式設計,不針對具體實現程式設計,即對介面程式設計,當需要進行變動時,只需變動介面即可。