C++ 工厂模式 类模板实现

文章目录

      • 1.简单工厂模式
      • 2.工厂方法模式
      • 3.抽象工厂模式
      • 4.模板类实现工厂模式

工厂模式正如其名字一样,用于产生对象的,往往是用于代替new,特别是在多态继承体系中,利用工厂模式可以将对象的产生延迟到子类中实现,而我们只需要知道子类的名称即可得到一个该子类的对象。就象我是我们需要购买手机,但是我们只需要知道手机的品牌和参数即可,而不需要知道手机是具体通过什么方式生产出来的。下面就介绍一下几种不同的工厂模式,而工厂类则实现了生产的细节,仅是提供了接口。而对应于编程的实现,我们往往是实现抽象基类,通过继承实现接口的方式来实现即可。

1.简单工厂模式

简单工厂模式就是用于获取建立在堆上的对象,根据具体的类编写具体的工厂生产方式。假如对于手机而言,我们常见的两大国产品小米和华为,那么针对小米的手机和华为的手机我们则需要具体的方法来生产相应的品牌的手机。

手机类:

class SmartPhone {
     
public:
    virtual void boot_up()=0;
    virtual ~SmartPhone() {
     

    }
};

class XiaoMi_Phone :public SmartPhone {
     
public:
    void boot_up() {
     
            cout << "XIAO MI" << endl;
        }
};

class HUAWEI_Phone :public SmartPhone {
     
public:
    void boot_up() {
     
        cout << "HUAWEI" << endl;
    }
};

现在针对两种手机品牌的手机,工厂需要根据品牌生产相应的手机。

enum
{
     
    HUAWEI,
    XIAOMI
};
class Phone_Factory {
     
public:
    SmartPhone* pruduce(int val) {
     
        switch (val)
        {
     
        case HUAWEI:
            return new HUAWEI_Phone;
        case XIAOMI:
            return new XiaoMi_Phone;
        default:
            return nullptr;
        }
    }
};

工厂测试:

int main()
{
     
    Phone_Factory factory;
    HUAWEI_Phone* p1 = dynamic_cast<HUAWEI_Phone*>(factory.pruduce(HUAWEI));
    XiaoMi_Phone* p2 = dynamic_cast<XiaoMi_Phone*>(factory.pruduce(XIAOMI));
    p1->boot_up();
    p2->boot_up();
}

简单工厂模式可以完成对对象的生成,但是可扩展性和维护性并不强,没多出一个品牌便需要修改已有的接口,这将给维护带来困难。因此,便有工厂方法模式的产生。

2.工厂方法模式

工厂方法模式就是定义一个抽象的工厂类,然后不同的类的生产工厂继承该类并将实现其接口,这样每当有新的类增加时,只需要进行扩展而无序修改,这就具有良好的扩展性。所以工厂应该如下的方式进行编写:

/*
析构以及构造使用编译器默认的版本,因此,这里没有写出。
*/
//抽象工厂
class Factory {
     
public:
   virtual SmartPhone * produce() = 0;
   virtual ~Factory() {
     
   };
};

class XIAOMI_Factory :public Factory {
     
public:
      XiaoMi_Phone * produce() {
     
        return new XiaoMi_Phone;
    }
};

class HUAWEI_Factory : public Factory{
     
public:
    HUAWEI_Phone * produce() {
     
        return new HUAWEI_Phone;
    }
};

假如我们现在有第三种手机品牌1+手机,则我们只需要继承抽象工厂类然后重载其中的纯虚函数即可,而不会去改动之前已经编写好的接口,因此,这就使得可扩展性增强。

3.抽象工厂模式

所为抽象工厂模式,也就是抽象方法模式的扩展,现在汽车行业也都逐渐向智能的方向发展,小米宣布开始制造汽车,而华为的鸿蒙系统也瞄准了汽车操作系统,假设现在,小米和华为都能生产汽车了,那么我们只需要对工厂进行添加接口就可以了。下面给出汽车的类:

class Car {
     
public:
    virtual void start() = 0;
    virtual ~Car() {
     

    }
};

class HUAWEI_Car :public Car {
     
public:
    void start() {
     
        cout << "HUAWEI CAR" << endl;
    }
};

class XIAOMI_Car : public Car {
     
public:
    void start() {
     
        cout << "XIAOMI CAR" << endl;
    }
};

则相应的工厂应该做出如下的扩展。

//抽象工厂
class Factory {
     
public:
   virtual SmartPhone * produce() = 0;
   virtual Car* produce_Car() = 0;
   virtual ~Factory() {
     
   };
};

class XIAOMI_Factory :public Factory {
     
public:
      XiaoMi_Phone * produce() {
     
        return new XiaoMi_Phone;
      }

      XIAOMI_Car* produce_Car() {
     
          return new XIAOMI_Car;
      }
};

class HUAWEI_Factory : public Factory{
     
public:
    HUAWEI_Phone * produce() {
     
        return new HUAWEI_Phone;
    }

    HUAWEI_Car* produce_Car() {
     
        return new HUAWEI_Car;
    }

};

测试:

 XiaoMi_Phone* phone1 = XIAOMI_Factory().produce();
 HUAWEI_Phone* phone2 = HUAWEI_Factory().produce();
 XIAOMI_Car* car1 = XIAOMI_Factory().produce_Car();
 HUAWEI_Car* car2 = HUAWEI_Factory().produce_Car();
 phone1->boot_up();
 phone2->boot_up();
 car1->start();
 car2->start();
 delete phone1;
 delete phone2;
 delete car1;
 delete car2;

4.模板类实现工厂模式

当每次有新的类出现的时候,我们都需要去增加接口以便能够产生新的产品,实际上STL库中已经存在一个功能类似万能工厂的函数,它就是make_shared函数,我们每次调用该函数的时候我们都能得到一个产生于堆上的对象的shared_ptr指针。所以,如果我们如果要实现一个万能工厂类,我们可以参考make_shared的方式写出一个万能工厂类。

先看一下make_shared的源码,如下:

template <class _Ty, class... _Types>
_NODISCARD
#if _HAS_CXX20
    enable_if_t<!is_array_v<_Ty>, shared_ptr<_Ty>>
#else // _HAS_CXX20
    shared_ptr<_Ty>
#endif // _HAS_CXX20
    make_shared(_Types&&... _Args) {
      // make a shared_ptr to non-array object
    const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...);
    shared_ptr<_Ty> _Ret;
    _Ret._Set_ptr_rep_and_enable_shared(_STD addressof(_Rx->_Storage._Value), _Rx);
    return _Ret;
}

源码看起来似乎很复杂,不过,没关系,我们只需要关注这两句便可。

template <class _Ty, class... _Types>
new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...);

用可变参数模板将类的构造函数的参数通过std::forward传入到new表达式中,这样便可以解决构造函数参数不定的问题了,因此,我们可用同样的方式来实现一个类模板,用于构建各种各样的对象。如下:

template<typename T>
class Factory_for_All
{
     
public:
    template<typename ... Args>
    static T* produce(Args  ... args);
};

template<typename T>
template<typename ... Args>
T* Factory_for_All<T>::produce(Args ... args) {
     
    return new T(std::forward<Args>(args)...);
}

现在对小米手机类进行扩展一下,多写几个不同参数的构造函数,对这个万能模板进行测试;

class XiaoMi_Phone :public SmartPhone {
     
public:
     XiaoMi_Phone(){
     }
     XiaoMi_Phone(const string & version_) {
     
         cout << "the version is " << version_ << endl;
     }
     XiaoMi_Phone(const string & version_, const int price) {
     
         cout << "the version is " << version_ << endl;
         cout << "the price is " << price << endl;
     }

    void boot_up() {
     
            cout << "XIAO MI" << endl;
           
        }
private:
};

测试主函数:

SmartPhone* p = Factory_for_All<XiaoMi_Phone>::produce(s,5);
SmartPhone* p1 = Factory_for_All<XiaoMi_Phone>::produce(s);
Car* c = Factory_for_All<XIAOMI_Car>::produce();
Car* c1 = Factory_for_All<HUAWEI_Car>::produce();
p->boot_up();
p1->boot_up();
c1->start();
c->start();
delete p;
delete c;
delete c1;
delete p1;

你可能感兴趣的:(设计模式,设计模式,多态)