设计模式一之策略模式(strategy)

本文探讨了软件设计中的动态行为扩展问题,通过引入鸭子模式,将鸭子的行为分解到独立的类中,实现了行为的灵活复用。重点阐述了如何在Duck类中加入行为接口,通过设置flyBehavior和quackBehavior变量,使得行为可以在运行时动态切换,避免了直接继承带来的维护难题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设现在有一个模拟鸭子的戏,此游戏设计了一个鸭子超类(Superclass),在超类中定义鸭子的形为 quackswim,并让其它的鸭子继承此超类。类图如下:

但假设现在鸭子的形为要扩展,要有一个会飞的行为,这时只需在基类Duck中添加fly()即可,类图如下:

但有一个问题是并非所有的鸭子都会飞,那么在超类中添加一个形为时,所有的子类中都会有这个行为,有一个解决方法是我们在不会飞 的鸭子中覆盖掉fly()行为,但当有更多的行为加进来时,这样的维护量是不可接受的,显然继承不是这里可以解决问题的最好方法。软件开发的一个不变的真理就是软件要一直改变,否则软件就会“死亡”。这就引出了第一个设计原则:找出应用程序中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起

我们希望鸭子的行为有弹性,因为没有弹性就会走到上面所述的困境中。有弹性的一个方法就是将鸭子的行为放在分开的类中,此类专门提供某种行为接口的实现。

设计原则二:针对接口编程,而不是针对实现编程

我们设计专门的接口代表每个行为,比方说,FlyBehavirQuackBehavior而行为的每个实现都将实现其中的一个接口。

行为类的类图如下所示:

 

 

这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。而我们可以新增一些行为,不会影响到既有的行为类,也不会影响“使用”到飞行行为的鸭子类。

修改Duck的设计,在其中添加两个变量分别为flyBehaviorquackBehavior, 这两个变量声明为接口,这样每个鸭子都可以动态的设置这些变量以在运行时引用正确的行为类型。同时删除flyquack方法,类图如下:

 

 

#include <iostream>

 

using namespace std;

class FlyBehavior

{

public:

FlyBehavior(){}

virtual ~FlyBehavior(){}

virtual void fly();

};

 

class FlyWithWings : public FlyBehavior

{

public:

FlyWithWings(){}

virtual ~FlyWithWings(){}

virtual void fly();

};

 

class FlyNoWay : public FlyBehavior

{

public:

FlyNoWay(){}

virtual ~FlyNoWay(){}

virtual void  fly();

};

 

class QuackBehavior

{

public:

QuackBehavior(){}

virtual ~QuackBehavior(){}

virtual void quack();

};

 

 

class Quack : public QuackBehavior

{

public:

Quack(){}

virtual ~Quack(){}

virtual void quack();

};

 

 

class MuteQuack : public QuackBehavior

{

public:

MuteQuack(){}

virtual ~MuteQuack(){}

virtual void quack();

};

 

 

class Squeak : public QuackBehavior

{

public:

Squeak(){}

virtual ~Squeak(){}

virtual void quack();

};

 

 

 

class Duck

{

public:

Duck(){}

~Duck(){}

void performQuack();

void swim();

void display();

void performFly();

protected:

FlyBehavior *flyBehavior;

QuackBehavior *quackBehavior;

};

 

 

class MallardDuck : public Duck

{

public:

MallardDuck();

~MallardDuck();

};

 

 

 

 

 

 

 

 

 

#include "strategy.h"

 

 

void FlyBehavior::fly()

{

 

}

 

 

void FlyWithWings::fly()

{

cout << " fly with wings" << endl;

}

 

 

void FlyNoWay::fly()

{

cout << "I can't fly" << endl;

}

 

 

void QuackBehavior::quack()

{

 

}

 

 

void Quack::quack()

{

cout << "Quack" << endl;

}

 

 

void MuteQuack::quack()

{

cout << "Silence" << endl;

}

 

 

void Squeak::quack()

{

cout  << "Squeak" << endl;

}

 

 

void Duck::performQuack()

{

quackBehavior -> quack();

}

 

void Duck::swim()

{

cout << "I'm swiming" << endl;

}

 

 

void Duck::display()

{

cout << "display" << endl;

}

 

 

void Duck::setQuackBehavior(QuackBehavior qb)

{

quackBehavior = qb;

}

 

 

MallardDuck::MallardDuck()

{

flyBehavior = new FlyWithWings;

quackBehavior = new Quack;

}

 

 

MallardDuck::~MallardDuck()

{

delete flyBehavior;

delete quackBehavior;

}

 

 

int main(int argc, char** argv)

{

MallardDuck *duck = new MallardDuck;

duck -> performFly();

duck -> performQuack();

}

 

 

 

上面的DUCK的子类初始化时就设定好了鸭子的行为,下面是动态的设定鸭子的行为。在 duck类中新增两个方法:类图如下

代码如下:

#include <iostream>

using namespace std;
class FlyBehavior
{
public:
	FlyBehavior(){}
	virtual ~FlyBehavior(){}
	
	virtual void		fly();
};

class FlyWithWings : public FlyBehavior
{
public:
	FlyWithWings(){}
	virtual ~FlyWithWings(){}
	virtual void		fly();
};

class FlyNoWay : public FlyBehavior
{
public:
	FlyNoWay(){}
	virtual ~FlyNoWay(){}
	virtual void 		fly();
};


class FlyRocketPowered : public FlyBehavior
{
public:
	FlyRocketPowered(){}
	virtual ~FlyRocketPowered(){}
	virtual void		fly();
};


class QuackBehavior
{
public:
	QuackBehavior(){}
	virtual ~QuackBehavior(){}
	virtual void		quack();
};


class Quack : public QuackBehavior
{
public:
	Quack(){}
	virtual ~Quack(){}
	virtual void		quack();
};


class MuteQuack : public QuackBehavior
{
public:
	MuteQuack(){}
	virtual ~MuteQuack(){}
	virtual void		quack();
};


class Squeak : public QuackBehavior
{
public:
	Squeak(){}
	virtual ~Squeak(){}
	virtual void		quack();
	
};



class Duck
{
public:
	Duck(){}
	virtual ~Duck(){}
	void			performQuack();
	void			swim();
	virtual void	display();
	void			performFly();
	void			setFlyBehavior(FlyBehavior *fb);
	void			setQuackBehavior(QuackBehavior *qb);
	
protected:
	FlyBehavior		*flyBehavior;
	QuackBehavior	*quackBehavior;
};


class MallardDuck : public Duck
{
public:
	MallardDuck();
	virtual ~MallardDuck();
#include "strategy.h"


void FlyBehavior::fly()
{

}


void FlyWithWings::fly()
{
	cout << " fly with wings" << endl;
}


void FlyNoWay::fly()
{
	cout << "I can't fly" << endl;
}


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


void QuackBehavior::quack()
{

}


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


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


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


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

void Duck::swim()
{
	cout << "I'm swiming" << endl;
}


void Duck::display()
{
	cout << "display" << endl;
}


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


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


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


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


MallardDuck::~MallardDuck()
{
	delete flyBehavior;
	delete quackBehavior;
}


void MallardDuck::display()
{
	cout << "I'm a mallarDuck";
}


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


ModelDuck::~ModelDuck()
{
	delete flyBehavior;
	delete quackBehavior;
}


int main(int argc, char** argv)
{
	MallardDuck *duck = new MallardDuck;
	duck -> performFly();
	duck -> performQuack();
	
	Duck *model = new ModelDuck;
	model -> performFly();
	model -> setFlyBehavior(new FlyRocketPowered);
	model -> performFly();
}

virtual void display();};class ModelDuck : public Duck{public:ModelDuck();virtual ~ModelDuck();};




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值