C++设计模式之工厂模式实例

工厂模式

工厂模式属于创建型模式,大致可以分为三类,简单工厂模式、工厂方法模式、抽象工厂模式。

简单工厂模式

简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一类产品类(这些产品类继承自一个父类或接口)的实例。假设有一个工厂,它能生产出A、B两种产品。当客户需要产品的时候一定要告诉工厂是哪种产品,是A还是B。当新增加一种新产品的时候,便需要修改工厂的类。

工厂方法模式

简单工厂模式的缺点是当新增加产品的时候需要修改工厂的类,这违反了开放封闭原则,即类、模板、函数可以扩展,但是不可以修改。工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。现在有A、B两种产品,那便开两个工厂,

工厂A负责生产A产品,工厂B负责生产B产品。客户不需要告诉工厂生产哪种产品,只需要告诉工厂生产即可。

抽象工厂模式

工厂方式模型的缺点是一个工厂只能生产一种产品,比如A工厂想生产A1、A2产品,B工厂想生产B1、B2产品。抽象模式提供一个创建一系列相关的接口,无需指定它们具体的类。

实例操作

下面,以抽象工厂模式为例实际演示工厂模式的威力。

背景:可适配地实现两个变量的多种类型运算方式,包括加法、减法等等。

数据文件

{
  "add":{
     "operation_name": "AddOperation",
     "a" : 2,
     "b" : 4
   },
   "sub":{
      "operation_name": "SubtractionOperation",
      "a" : 10,
      "b" : 3
   }  
}

基础类

#include "base_operation.h"

namespace searcher {

BaseOperationRegistry* GlobalBaseOperationRegistry() {
  static BaseOperationRegistry helper;
  return &helper;
}

int BaseOperation::Init(float a, float b) { }

void BaseOperation::Run() { } 
} // namesapce searcher
#pragma once
#include <string>
#include <unordered_map>
#include <functional>

namespace searcher {

class BaseOperation {
 public:
     BaseOperation() {}
     
     virtual ~BaseOperation() {}
     
     virtual int Init(float a, float b);

     virtual void Run();
 public:
   float a_;
   float b_;
   float result_;
};

class BaseOperationRegistry {
 public:
     using BaseOperationFactory = std::function<BaseOperation*(void)>;
     using BaseOperationFactoryMap = std::unordered_map<std::string, BaseOperationFactory>;
 public:
     BaseOperationRegistry() {}
     void Register(const std::string &name, const BaseOperationFactory &factory) {
        base_operation_factory_map_[name] = factory;
     }
     BaseOperation* Create(const std::string &name) {
        auto it = base_operation_factory_map_.find(name);
        if (it != base_operation_factory_map_.end()) {
           return it->second();
        }
        return nullptr;
     }
 private:
     BaseOperationFactoryMap base_operation_factory_map_;
};

BaseOperationRegistry* GlobalBaseOperationRegistry();

class BaseOperationHelper {
 public:
     using BaseOperationFactory = std::function<BaseOperation*(void)>;
     using BaseOperationFactoryMap = std::unordered_map<std::string, BaseOperationFactory>;
 public:
     BaseOperationHelper(const std::string &name, const BaseOperationFactory &factory) {
        GlobalBaseOperationRegistry()->Register(name, factory);
     }
 private:
     static BaseOperationFactoryMap base_operation_factory_map_;
};

#define REGISTER_BASE_OPERATION(name, factory) \
    static BaseOperationHelper helper_obj##__COUNTER__(name, factory);

#define REGISTER_BASE_OPERATION_SIMPLE(name, type) \ 
    REGISTER_BASE_OPERATION(name, []() -> type* {return new type(); })

} // namespace searcher

通用接口

#include <iostream>
#include <fstream>
#include "json/json.h"
#include "general_operation_processor.h"
#include "base_operation.h"

namespace searcher {
  int GeneralOperationProcessor::Init(std::string &json_file)
  {
    std::ifstream ifs(json_file.c_str());
    if (ifs.fail()) {
       return -1;
    }    
    
    Json::Reader reader;
    Json::Value root;

    if (!reader.parse(ifs, root, false) || not root.isObject()) {
       return -1;
    }

    try
    {
       const std::vector<std::string>& vecs = root.getMemberNames();
       for (unsigned int i = 0; i < vecs.size(); ++i)
       {
          std::string id = vecs[i];
          const Json::Value& jv = root[id.c_str()];
          if (!jv.isMember("operation_name") || !jv.isMember("a") || !jv.isMember("b")) {
             continue;
          }
          std::string operation_name = jv["operation_name"].asString();
          float a = jv["a"].asDouble();
          float b = jv["b"].asDouble();
          BaseOperation* operation = GlobalBaseOperationRegistry()->Create(operation_name);
          if (nullptr == operation) {
             continue;
          }
          if (operation->Init(a,b) != 0) {
              delete operation;
              continue;
          } 
          auto* operation_profile = new OperationProfile;
          operation_profile->id = id;
          operation_profile->a = a;
          operation_profile->b = b;
          operation_profile->operation_name = operation_name;
          operation_profile->op.reset(operation);
          operation_profile_map_[id].reset(operation_profile);
        }
    }
    catch(const std::exception& e) {
       return -2;
    }
    return 0;
  }

  void GeneralOperationProcessor::Run()
  {
    for (auto iter = operation_profile_map_.begin(); iter != operation_profile_map_.end(); ++iter) {
        const auto &profile = iter->second;
        profile->op->Run(); 
    }
    Print(); 
  }

  void GeneralOperationProcessor::Print() const
  {
    for (auto iter = operation_profile_map_.begin(); iter != operation_profile_map_.end(); ++iter) {
        const auto &profile = iter->second;
        std::cout << "operation:" << profile->operation_name
                  << " ,a:" << profile->op->a_
                  << " ,b:" << profile->op->b_
                  << " ,result:" << profile->op->result_ << std::endl;
    }
  } 
} // searcher
#pragma once
#include <memory>
#include <string>
#include <unordered_map>
#include "base_operation.h"

namespace searcher {

class BaseOperation;

struct OperationProfile {
    std::string id;
    std::string operation_name;
    float a = 0.f;
    float b = 0.f;
    std::unique_ptr<BaseOperation> op;
};

class GeneralOperationProcessor {
 public:
    int Init(std::string &json_file);
    void Run();
    void Print() const;
 private:
    std::unordered_map<std::string, std::unique_ptr<OperationProfile>> operation_profile_map_;
};

} // searcher

子类-加法运算

#include "add_operation.h"

namespace searcher {
  int AddOperation::Init(float a, float b) 
  {
    a_ = a;
    b_ = b;
    return 0;
  }

  void AddOperation::Run() {
    result_ = a_ + b_;
  }

} // searcher
#pragma once
#include "base_operation.h"

namespace searcher {

class AddOperation : public BaseOperation {
 public:
   AddOperation() {}
   virtual ~AddOperation() {}
   virtual int Init(float a, float b);
   virtual void Run();
};

REGISTER_BASE_OPERATION_SIMPLE("AddOperation", AddOperation);

}; // searcher

子类-减法运算

#include "subtraction_operation.h"

namespace searcher {
  int SubtractionOperation::Init(float a, float b)
  {
    a_ = a;
    b_ = b;
    return 0;
  }

  void SubtractionOperation::Run() {
    result_ = a_ - b_;
  }

} // searcher
#pragma once
#include "base_operation.h"

namespace searcher {

class SubtractionOperation : public BaseOperation {
 public:
   SubtractionOperation() {}
   virtual ~SubtractionOperation() {}
   virtual int Init(float a, float b);
   virtual void Run();
};

REGISTER_BASE_OPERATION_SIMPLE("SubtractionOperation", SubtractionOperation);

}; // searcher

最后,贴上g++运行指令:

g++ -std=c++11 -g -I../../json/include/ -L../../json/lib/ base_operation.cpp add_operation.cpp subtraction_operation.cpp general_operation_processor.cpp main.cpp -o main -ljson
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值