最近在看设计模式一本书,发现策略模式和简单工厂模式很像,刚刚开始我还以为是一样的,总感觉没什么区别,后来才看明白,有一点点个人的理解,记录下来,方便下次复习以及理解。
概念理解:
多态:C++的多态性用一句话概括就是,在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数
策略模式:定义了实现,用接口来封装起来,通过构造器的构造参数不同使得实现有所不同。
简单工厂模式:定义了实现,用接口来封装起来,由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
代码例子:
多态:
class classA
{
public:
classA();
virtual void test();
};
class classB : public classA
{
public:
classB();
void test();
};
classA::classA()
{
}
void classA::test()
{
printf("classA test Func\n");
}
classB::classB()
{
}
void classB::test()
{
printf("classB test Func\n");
}
测试代码:
int main(int argc, char*argv[])
{
classA *pBaseClass = new classA();
pBaseClass->test(); //输出结果是 : classA test Func
classB *pSubClass = new classB();
pSubClass->test(); //输出结果是 classB test Func
classA *pData = new classB();
pData->test(); //输出结果是 classB test Func
return 0;
}
注意:为什么一定要加virtual才有多态的效果,因为不加virtual 的话 编译器在编译的时候,就已经确定了对象调用的函数的地址,要解决这个问题就要使用迟绑定(late binding)技术。当编译器使用迟绑定时,就会在运行时再去确定对象的类型以及正确的调用函数。而要让编译器采用迟绑定,就要在基类中声明函数时使用virtual关键字(注意,这是必须的,很多学员就是因为没有使用虚函数而写出很多错误的例子),这样的函数我们称为虚函数。一旦某个函数在基类中声明为virtual,那么在所有的派生类中该函数都是virtual,而不需要再显式地声明为virtual。
策略模式:
class compositor
{
public:
compositor();
virtual void compose();
};
class compositorA : public compositor
{
public:
compositorA();
void compose();
};
class compositorB : public compositor
{
public:
compositorB();
void compose();
};
class compsotion
{
public:
compsotion(compositor* p);
void test();
private:
compositor* pDate;
};
compositor::compositor()
{
}
void compositor::compose()
{
printf("compositor compose Func ");
}
compositorA::compositorA()
{
}
void compositorA::compose()
{
printf("compositorA compose Func ");
}
compositorB::compositorB()
{
}
void compositorB::compose()
{
printf("compositorB compose Func ");
}
compsotion::compsotion(compositor* p):pDate(p)
{
}
void compsotion::test()
{
pDate->compose();
}
测试代码如下:
int main(int argc, char* argv[])
{
int i = 2;
compsotion * pComposition;
switch(i){
case 3:
pComposition = new compsotion(new compositorB());
break;
case 2:
pComposition = new compsotion(new compositorA());
break;
case 1:
pComposition = new compsotion(new compositor());
break;
default:
retuan 0;
}
pComposition->test();
return 0;
}
输出结果:
compositorA compose Func
当我们改变i的值,会进入不同的处理函数。
简单工厂模式:
class AbsClass
{
public:
AbsClass();
virtual void test();
};
class ClassA:public AbsClass
{
public:
ClassA();
void test();
};
class ClassB:public AbsClass
{
public:
ClassB();
void test();
};
class CSimpleFactory
{
public:
CSimpleFactory();
static AbsClass* createClass(int type);
};
CSimpleFactory::CSimpleFactory()
{
}
AbsClass* CSimpleFactory::createClass(int type)
{
AbsClass *cs = NULL;
switch(type){
case 1:
cs = new AbsClass();
break;
case 2:
cs = new ClassA();
break;
case 3:
cs = new ClassB();
break;
default:
break;
}
return cs;
}
AbsClass::AbsClass()
{
}
void AbsClass::test()
{
printf("AbsClass::test\n");
}
ClassA::ClassA()
{
}
void ClassA::test()
{
printf("ClassA::test\n");
}
ClassB::ClassB()
{
}
void ClassB::test()
{
printf("ClassB::test\n");
}
测试代码如下:
int main(int argc, char*argv[])
{
int i = 2;
AbsClass* pDate = CSimpleFactory::createClass(i);
if(pDate)
pDate->test();
return 0;
}
输出结果: ClassA::test 当改变条件type时,会得到不同行为的对象,当然也就会有不同的行为了。
总结:
策略模式和简单工厂模式看起来非常相似,都是通过多态来实现不同子类的选取,这种思想从刚刚的例子中也可以看出来。如果从使用这两种模式的角度来看的话,我们会发现在简单工厂模式中我们只需要传递相应的条件就能得到想要的一个对象,然后通过这个对象实现算法的操作。而策略模式,使用时必须首先创建一个想使用的类对象,然后将该对象最为参数传递进去,通过该对象调用不同的算法。在简单工厂模式中实现了通过条件选取一个类去实例化对象,策略模式则将选取相应对象的工作交给模式的使用者,它本身不去做选取工作。简单理解为策略模式使用前需要知道具体某一个对象,简单工厂则是通过条件创造对象,两者都是通过多态调用具体算法。