几个月之前,我在一家小的软件公司上班。在我来到这家公司的时候,这家公司里面负责C++开发的程序员老L是一个二把刀。原来他是做C#开发的,后来不知道为什么来到这家小公司做C++开发的。我来到公司的第一天就开始了加班的生活,比较累,也很郁闷。做IT的,加班,倒也算可以接受,但是有一点,让很多人会非常的郁闷。那就老L这人为人做事,实在让人有点郁闷。他从不让人修改他写过的代码,这是让我非常郁闷的。为此我和他也吵过,但是死活不相信,坚决不让别人修改他写过的代码。
我不知道大家在遇到这样的情况该怎么办?也许大家有一些技术上的高招,也许和我一样没技术含量一般和他斗斗嘴,然后偷偷改几个必须修改的类。但是事情过去了两个月左右了,当我再次回忆此次事情的时候,我终于觉得还是自己技术太菜。如果要是我的技术更高一点,或许摩擦会少一点。特别是我开始阅读设计模式这些书之后,再来回顾那些曾经老人们说过的话,写代码要“高内聚,低耦合”。心里自然会明亮了很多,感叹老人们的技术的厉害。好的代码,能够减少两个程序员之间很多的矛盾。
言归正传。对于工厂模式,之前看了一点,囫囵吞枣。终于决定再次看一遍,虽挑灯夜战,但是也觉得很幸福。人只有在经历过磨难,才觉得普通的生活就是幸福。所以再次劝大家看书,务必要细心。浮躁的人成不了大事。
工厂模式分为普通工厂模式和抽象工厂模式。相比于普通工厂模式,抽象工厂模式能够做到更加的低耦合。下面我的例子是模仿大话设计模式里面的例子。
学雷锋做好事:
我们现在有一个雷锋类,雷锋类里面有一个成员函数做好事(函数)。
class Leifeng { public: Leifeng(){cout<<"<Leifeng>"<<endl;} virtual ~Leifeng(){cout<<"<~Leifeng>"<<endl;} public: virtual void DoGoodThing() = 0; };
当然,雷锋做好事,全中国只有一个雷锋,不能全指望雷锋做好事。咱们也得动动手,学雷锋做好事。于是全国各个不同年级的学生都开始学做好事,小学生,中学生,高中生,大学生,都不甘落后学雷锋做好事。于是乎我们就需要从雷锋继承做好事的精神,动手做好事。
创建小学生学雷锋做好事的类
class CXiaoxuesheng: public Leifeng { public: CXiaoxuesheng() { cout<<"<CXiaoxuesheng>"<<endl; } ~CXiaoxuesheng() { cout<<"<~CXiaoxuesheng>"<<endl; } public: virtual void DoGoodThing() { cout<<"小学生,帮老太太扫地"<<endl; } };
创建中学生学雷锋做好事的类
class CZhongxuesheng: public Leifeng { public: virtual void DoGoodThing() { cout<<"中学生,帮老太太擦玻璃"<<endl; } };
创建高中生学雷锋做好事的类
class CGaozhongsheng: public Leifeng { public: virtual void DoGoodThing() { cout<<"高中生,帮老太太买米"<<endl; } };
创建大学生学雷锋做好事的类
class CDaxuesheng: public Leifeng { public: virtual void DoGoodThing() { cout<<"大学生,给老太太看病"<<endl; } };
这个时候,我们可以根据不同的学生类型来产生不同的学生对象。我们需要有一个工厂类。(具体为什么这样做,先看完了全文,然后自然会明白的)
创建一个工厂类
class CFactory { public: virtual ~CFactory(){} public: static Leifeng *GetHaoren(char ch)//x,z,g,d分别表示小学生,中学生,高中生,大学生 { switch(ch) { case 'x': return new CXiaoxuesheng(); case 'z': return new CZhongxuesheng(); case 'g': return new CGaozhongsheng(); case 'd': return new CDaxuesheng(); default: return NULL; } } };
在主函数里面我们现在可以完成调用工厂模式调用过程:
Leifeng *pLeifeng = CFactory::GetHaoren('x');// pLeifeng->DoGoodThing();
以上就是一个完整的工厂模式的设计。可以对照下面的图片理解一下:
工厂模式,说白了就是一个带有虚函数的类A(通常是纯需函数),再根据不同的情况,对该类进行派生,形成多个派生类A1,A2,A3,...,An。另外一个就是工厂类Factory,这个Factory有一个成员函数,专门根据不同的情况产生派生类An对象,并且将派生类对象的指针返回。我们定义一个类A的指针,把之前返回的值,赋值非类A的指针。这个时候,我们就可以调用类A的成员虚函数(这个时候,就调用的是派生类中虚函数的实现过程)。
抽象工厂模式:
抽象工厂模式,就是将工厂类再次进行抽象。
这样,我们的工厂类仅仅申明可以建立不同的做好事人员对象,并不做什么实际工作。
class CFactory { public: CFactory(){} virtual ~CFactory(){} public: virtual Leifeng *GetHaoren() = 0; };
这个时候,我们需要根据实际的情况来看,我们有小学生做好事,中学生做好事,高中生做好事,大学生做好事。因此我们需要对他们进行实例化。
class CXiaoxueshengFactory:public CFactory { public: virtual Leifeng *GetHaoren() { return new CXiaoxuesheng(); } }; class CZhongxueshengFactory: public CFactory { public: virtual Leifeng* GetHaoren() { return new CZhongxuesheng(); } }; class CGaozhongshengFactory:public CFactory { public: virtual Leifeng* GetHaoren() { return new CGaozhongsheng(); } }; class CDaxueshengFactory:public CFactory { public: virtual Leifeng * GetHaoren() { return new CDaxuesheng(); } };
此时我们可以在调用的时候,就可以有如下操作:
int main() { CFactory * pFactory = new CXiaoxueshengFactory(); Leifeng * pLeifeng = pFactory->GetHaoren(); pLeifeng->DoGoodThing(); delete pLeifeng; return 0; }
以上就是学雷锋做好事抽象工厂模式,下面是完整的代码。
#include <iostream> using namespace std; class Leifeng { public: Leifeng(){cout<<"<Leifeng>"<<endl;} virtual ~Leifeng(){cout<<"<~Leifeng>"<<endl;} public: virtual void DoGoodThing() = 0; }; class CXiaoxuesheng: public Leifeng { public: CXiaoxuesheng() { cout<<"<CXiaoxuesheng>"<<endl; } ~CXiaoxuesheng() { cout<<"<~CXiaoxuesheng>"<<endl; } public: virtual void DoGoodThing() { cout<<"小学生,帮老太太扫地"<<endl; } }; class CZhongxuesheng: public Leifeng { public: virtual void DoGoodThing() { cout<<"中学生,帮老太太擦玻璃"<<endl; } }; class CGaozhongsheng: public Leifeng { public: virtual void DoGoodThing() { cout<<"高中生,帮老太太买米"<<endl; } }; class CDaxuesheng: public Leifeng { public: virtual void DoGoodThing() { cout<<"大学生,给老太太看病"<<endl; } }; class CFactory { public: CFactory(){} virtual ~CFactory(){} public: virtual Leifeng *GetHaoren() = 0; }; class CXiaoxueshengFactory:public CFactory { public: virtual Leifeng *GetHaoren() { return new CXiaoxuesheng(); } }; class CZhongxueshengFactory: public CFactory { public: virtual Leifeng* GetHaoren() { return new CZhongxuesheng(); } }; class CGaozhongshengFactory:public CFactory { public: virtual Leifeng* GetHaoren() { return new CGaozhongsheng(); } }; class CDaxueshengFactory:public CFactory { public: virtual Leifeng * GetHaoren() { return new CDaxuesheng(); } }; int main() { CFactory * pFactory = new CXiaoxueshengFactory(); Leifeng * pLeifeng = pFactory->GetHaoren(); pLeifeng->DoGoodThing(); delete pLeifeng; return 0; }
最后,我们回过头来在看代码,我们在main函数中,只需要改动new后面的CXiaoxueshengFactory类类型,就可以产生不同的对象(比如中学生,大学生等),这个时候就可以让别的学生做其他的好事。如果我们在做好事的人里面,添加社会义工这一项,那么我们只需要继续从leifeng这个类中继承一下。然后再工厂类中继承一下,产生新类,用于生成义工这一个类对象。 我们完全不需要修改原来别人的代码,就能够完成添加不同的学雷锋群体,以及他们具体做什么好事。
再回头想想我的同事老L不让我修改他的代码。假设他当时能够写成这样的代码,我和他之间就没有任何的冲突可产生。还是自己的能力太弱了。呵呵