现在的位置: 首页 > 综合 > 正文

设计模式之——工厂模式

2011年01月10日 ⁄ 综合 ⁄ 共 4544字 ⁄ 字号 评论关闭

几个月之前,我在一家小的软件公司上班。在我来到这家公司的时候,这家公司里面负责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不让我修改他的代码。假设他当时能够写成这样的代码,我和他之间就没有任何的冲突可产生。还是自己的能力太弱了。呵呵

抱歉!评论已关闭.