C++实现Creational - Simple Factory模式

Simple Factory模式根据提供给它的数据,返回几个可能类中的一个类的实例,通常这个类都有一个公共的父类和一些公共的方法。需要说明的是Simple Factory模式并非GoF所定义的23个设计模式中的一员。

 

在国外,关于一个人的全名,通常有两种写法:一个人的姓名,如果中间有,则姓在前,名在后;如果中间没有,那么空格前为名,后为姓。比如:“Bill Gates”,那么Bill就是名,Gates就是姓;“Clinton, Bill”,那么Clinton就是姓,Bill就是名。

 

现在假定有一个问题:随机用上述两种不同的方式输入全名,用程序区分其姓和名。对于这样的问题,用Simple Factory模式来解决是很方便的。

 

下图就用Simple Factory模式解决这个问题的类图:

 

下面是在C++中的具体实现:

// SimpleNameFactory.h

#include <string>

#include <memory>

#include <iostream>

using namespace std;

 

// 这是一个和模式无关的工具类

class PatUtility

{

public:

         string& trim(string& s);      // 用来删除一个字符串前面或者后面的空格

};

 

// 公共父类。在C++中,

// 1. 父类的析构函数一般必须是virtual

// 2. 准备被子类重写的成员函数,也必须是virtual

class FullNamer

{

public:

         virtual string getLastName();

         virtual string getFirstName();

 

         virtual ~FullNamer()

         {

                   cout << "in the destructor of FullNamer" << endl;

         }

protected:

         string last_name;

         string first_name;

};

 

// 名在前

class FirstNameFirst : public FullNamer

{

public:

         FirstNameFirst(const string& str);

         ~FirstNameFirst()

         {

                   cout << "in destructor of FNF" << endl;

         }

};

 

// 姓在前

class LastNameFirst : public FullNamer

{

public:

         LastNameFirst(const string&);

         ~LastNameFirst()

         {

                   cout << "in destructor of LNF" << endl;

         }

};

 

// 简单工厂类

class NameSimpleFactory

{

public:

         // 返回类型是auto_ptr<FullNamer>,它可以理解为可以自动

         // 销毁对象的FullNamer*

         auto_ptr<FullNamer> createFullNamer(const string&);

};

// SimpleNameFactory.cpp

#include "SimpleNameFactory.h"

 

// 删除一个字符串前面和后面的空白

string& PatUtility::trim(string& s)

{

       if(s.empty()) return s;

       s.erase(0, s.find_first_not_of(" "));

       s.erase(s.find_last_not_of(" ") + 1);

 

       return s;

}

 

// 返回名

string FullNamer::getFirstName()

{

       return first_name;

}

 

// 返回姓

string FullNamer::getLastName()

{

       return last_name;

}

 

// FirstNameFirst类的构造函数

FirstNameFirst::FirstNameFirst(const string& str)

{

       PatUtility pu;

       // 名在前,空格符为分隔符

       size_t i = str.find_last_of(" ");

       if(i != string::npos)

       {

              first_name = pu.trim(str.substr(0, i));

              last_name = pu.trim(str.substr(i + 1));

       }

       else

       {

              first_name = "";

              last_name = str;

       }

}

 

// LastNameFirst类的构造函数

LastNameFirst::LastNameFirst(const string& str)

{

       PatUtility pu;

       // 姓在前,逗号为分隔符

       size_t i = str.find_last_of(",");

       if(i != string::npos)

       {

              first_name = pu.trim(str.substr(i + 1));

              last_name = pu.trim(str.substr(0, i));

       }

       else

       {

              first_name = "";

              last_name = str;

       }

}

 

auto_ptr<FullNamer> NameSimpleFactory::createFullNamer(const string& entry)

{

       size_t i = entry.find_last_of(",");

       // 在下面的if语句中,决定了到底返回那个类的实例,这就是Simple Factory

       // 模式的控制中枢所在

       if(i != string::npos)  // 如果提供的全名包含“,”

       {

              // 如果不使用auto_ptr,那么通过new LastNameFirst(entry)动态分配到

              // 内存不会自动释放

              auto_ptr<FullNamer> p(new LastNameFirst(entry));

              return p;

       }

       else                             // 如果提供的全名不包含“,”

       {

              auto_ptr<FullNamer> p(new FirstNameFirst(entry));

              return p;

       }

}

 

// 测试代码

#include "SimpleNameFactory.h"

 

int main(void)

{

         // 定义一个NameSimpleFactory对象

         NameSimpleFactory nsf;

 

         string entry1("CLINTON,     BILL");

         // 如果不考虑自动内存释放,下面的语句类似于(当然实际上这么做事不行的,除非createFullNamer

         // 返回类型为FullNamer*,除此之外,当fn1使用完成后,要delete fn1;,否则会有内存泄漏)

         // FullNamer *fn1 = nsf.createFullNamer(entry1);

         auto_ptr<FullNamer> fn1(nsf.createFullNamer(entry1));

         cout << "First name is: " << fn1->getFirstName() << ", and last name is: " << \

fn1->getLastName() << endl;

 

         string entry2("BILL  GATES");

         auto_ptr<FullNamer> fn2(nsf.createFullNamer(entry2));

         cout << "First name is: " << fn2->getFirstName() << ", and last name is: " << \

fn2->getLastName() << endl;

 

         return 0;

}

 

上面的程序运行结果:

First name is: BILL, and last name is: CLINTON

First name is: BILL, and last name is: GATES

in destructor of FNF

in the destructor of FullNamer

in destructor of LNF

in the destructor of FullNamer

 

输出结果符合预期。

 

Simple Factory的优点和缺点:

优点:客户端程序无需知道返回具体类的实例,这项工作全部由Factory类去完成,这就隔离了客户端代码。

缺点:要返回哪个类是由Factory类来决定的,因此,比如当增加一个具体类时,Factory代码必须改动。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值