C++实现Creational - Simple Factory模式

来源:互联网 发布:传智python视频百度云 编辑:程序博客网 时间:2024/05/29 14:49

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>

usingnamespace 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代码必须改动。

 
转:http://patmusing.blog.163.com/blog/static/135834960201002323120571/
原创粉丝点击