设计模式之策略模式

代码设计原则

1.找出应用中(一个类具有的方法中)可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码(功能)混在一起。

这句话很好理解,但是要怎么个独立法才是关键,也是很疑惑的地方,那请继续往下看吧。


2.针对接口编程,而不是针对实现编程。

假如现在你要写一个类具有多个方法,即有多个功能。那么怎么来写代码或者说怎么来定义这个类呢?

现在有两种方式:

       1)  如果在基类本身中直接定义这些功能的虚方法,子类通过继承来实现这些功能,这种方式就是针对实现编程;其实针对实现编程就是将某一个类的方法定义太死(即因为某个类要实现一个功能而为这个类定义一个方法),使其没有拓展性,也就是没有对其(该方法或功能)进行再抽象,可与针对接口编程对比理解。

           这个方式有什么不好了,就是没法拓展,设计模式里的说法叫没有弹性,因为要对这个类增加一个方法即功能,得去基类中加,就会对所有从这个类继承的子类造成影响,都得去改代码,这个一看就望而生畏了,然后我们通常就会作出从子类增加一个方法的方式来达到这个目的,然后我们就周而复始的这么干活,然后我们就越来越觉得我们写的代码很垃圾,组织结构越来越乱,而下次想在其它工程中再用这些代码或功能的时候感觉要搬过去很麻烦或是很难再用(如果你有这样的困惑,去看设计模式吧,会有相见恨晚的感觉,多么痛的领悟额额)。

           2)如果我们不直接在基类中直接定义这些方法(功能),而是将这些方法(第一个设计原则提到的)独立成一个类(一个接  口)InterfaceFunction来单独定义它,而在基类中增加一个这个方法接口定义的成员InterfaceFunction IFun,如果要增加对这个方法的实现只需新继承这个接口再实现,并赋给基类的方法接口定义的成员IFun, 这种方式叫做针对接口编程;

           这个方式有什么好处了,显然我们可以在以后的编程中来动态实现这个方法接口,如果新增加方法或是同一个方法不同实现都    可以新继承然后直接实现,而不会对其它继承至这个基类的子类有任何影响,在代码的重用性上面,在其它的工程中也可以直接运用这个方法接口实现,而不会有将基类也带入其它工程的苦恼。这种方式也叫运行时动态绑定,即在程序运行的过程中可以动态改变这个方法的实现,即动态赋值的过程。

3.多用组合,少用继承。

在上面针对接口编程中,将类的方法定义成抽象接口类,当我们在实现这个类的时候实际上是用两个类的组合来完成这个类的定义及实现,而不是采


c代码示例:(参考Head+First+设计模式)

//fly method interface
typedef struct _IFlyInterface{
	void (*fly)();
}IFlyInterface;

//quack method interface
typedef struct _IQuackInterface{
	void (*quack)();
}IQuackInterface;

//针对接口编程类定义
typedef struct _CDuck{
	IFlyInterface* pIFlyInterface;
	IQuackInterface* pIQuackInterface;
	void (*performFly)( CDuck* this );
	void (*siwm)( CDuck* this );
	void (*display)( CDuck* this );
}CDuck;

//针对实现编程类定义,也就是我们拿起来开始写代码干的事
typedef struct CDuck{
	void (*fly)( CDuck* this );
	void (*quack)( CDuck* this );
	void (*siwm)( CDuck* this );
	void (*display)( CDuck* this );
};


/应用///
//该fly方法可以在不同的地方使用而与CDuck类无关(可重用性)
void fly1()
{
	printf( "i can fly1" );
}
void fly2()
{
    printf( "i can fly2" );
}
IFlyInterface* pIFlyInterface = (IFlyInterface*)malloc( sizeof(IFlyInterface) );
//可以设置不同的飞行方式,即fly方法的不同实现(fly1 or fly2 ...)(拓展性)
//pIFlyInterface->fly = fly1;
pIFlyInterface->fly = fly2;
//CDuck
void performFly( CDuck* this )
{
	this->pIFlyInterface->fly();
}
CDuck* pMyDuck = (CDuck*)malloc( sizeof(CDuck) );
//可以对CDuck的pIFlyInterface进行动态赋值,达到运行时动态绑定的效果
//而不是直接一个方法写死,只能调一个方法
pMyDuck->pIFlyInterface = pIFlyInterface;
pMyDuck->performFly = performFly;

//invoke
pMyDuck->performFly( pMyDuck );


//如果我们采用第二种定义方式,即针对实现编程的话,就会碰到如下问题
//如果以后这个类要增加一个fly方法,我们可能就会去里面定义一个fly2方法,如果这个
//类是基类的话,那么所有的子类都会受到影响或者我们选择在继承的子类中重新定义一个
//fly方法,但是这样显得我们的代码组织结构很乱,到后面越来越乱,而且如果这个fly方法
//后面在别的工程里用的时候就会跟基类CDuck搭上关系,不方便移植。

上面的这个模型就叫做策略模式(Strategy Pattern),定义如下:

策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

其实什么模式不重要,主要是以后写代码的时候知道怎么去组织就好,写得不对的地方还请见谅,指证(个人看书后见解)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值