1. 程式人生 > >工廠方法(虛構造器)

工廠方法(虛構造器)

核心 form class 具體類 同時 {} 多個 道具 cat

工廠方式的核心是定義一個抽象工廠接口類,將對象的創建工作推遲到工廠接口類的子類中

即不同對象創建依賴繼承自工廠基類的關聯工廠子類。

相較於簡單工廠,工廠方法模式符合開閉原則,同時實現了解耦,但出現了類膨脹即所有產品的實例對象都需要有各自的工廠
如果是要克服簡單工廠模式的局部耦合缺陷,也可以考慮使用C++模板形式實現簡單工廠。
base.h

#ifndef BASE_H
#define BASE_H

#include <string>
using namespace std;

class IBase
{
public:
    virtual ~IBase();
    virtual const string& getName() const;
    virtual void setName(const string& name);
protected:
    IBase();
    IBase(const string& name);
private:
    string m_name;
};

#endif // BASE_H

base.cpp

#include <iostream>
#include "base.h"

const string& IBase::getName() const
{
    return m_name;
}

void IBase::setName(const string& name)
{
    m_name = name;
}

IBase::IBase()
{
    cout << "constructor IBase" << endl;
}

IBase::IBase(const string& name)
{
    m_name = name;
}

IBase::~IBase()
{
    cout << "destructor IBase" << endl;
}

imp.h

#ifndef IMP_H
#define IMP_H

#include "base.h"

class CImpSamA : public IBase
{
public:
    CImpSamA();
    CImpSamA(string name);
    ~CImpSamA();
};

class CImpSamB : public IBase
{
public:
    CImpSamB();
    CImpSamB(string name);
    ~CImpSamB();
};
#endif // IMP_H

imp.cpp

#include <iostream>
#include "imp.h"

CImpSamA::CImpSamA():IBase("CImpSamA")
{
    cout << "constructor CImpSamA NoParam " << endl;
}

CImpSamA::CImpSamA(string name):IBase(name)
{
    cout << "constructor CImpSamA " << endl;
}

CImpSamA::~CImpSamA()
{
    cout << "destructor CImpSamA " << endl;
}

CImpSamB::CImpSamB():IBase("CImpSamB")
{
    cout << "constructor CImpSamB NoParam " << endl;
}

CImpSamB::CImpSamB(string name):IBase(name)
{
    cout << "constructor CImpSamB " << endl;
}

CImpSamB::~CImpSamB()
{
    cout << "destructor CImpSamB " << endl;
}

factory.h

#ifndef FACTORY
#define FACTORY

#include "base.h"

class CFactoryA
{
public:
    //返回CImpSamA*類型
    template<class T>
    static T* Create()
    {
         return new T();
    }
};

class CFactoryB
{
public:
    //返回IBase*類型
    template<class T>
    static IBase* Create()
    {
        return new T();
    }
};

#endif // FACTORY

main.cpp

#include <QCoreApplication>
#include <iostream>
#include "factory.h"
#include "imp.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    //返回CImpSamA*類型
    IBase* pImp = CFactoryA::Create<CImpSamA>();
    if(NULL != pImp)
    {
        pImp->setName("New IMPA");
        cout << pImp->getName() << endl;
        delete pImp;
        pImp = NULL;
    }
    //返回IBase*類型
    pImp = CFactoryB::Create<CImpSamB>();
    if(NULL != pImp)
    {
        cout << pImp->getName() << endl;
        delete pImp;
        pImp = NULL;
    }

    return a.exec();
}

優點:

  • 相較於簡單工廠,將原本耦合在一個接口的創建方法,通過模板實例化多個具體創建實現,解除了局部耦合。
  • 相較於工廠方法,避免了不同工廠基類造成的類膨脹。

缺點:

  • 使用模板經過二次編譯存在開銷(編譯期)
  • 需要工廠的具體產品類型對外可見才能在外部進行創建工作,違反了封裝特性,必須在調用模板的地方或者模板實現中引入(有聲明)相關產品對象。
  • 依然不符合開閉原則,一旦需要引入新的產品類型,需要增加新的模板實例化調用代碼。

拋開優缺點,簡單工廠是將產品創建工作集中到一個函數來創建,模板方法實現實際上是通過模板擴展出多個函數達到創建不同產品的目的。

下面來看真正的 工廠方法。
factory.h

#pragma once

#include "imp.h"

class ISplitterFactory
{
public:
        virtual ISplitter* CreateSplitter() = 0;
        virtual ~ISplitterFactory(){}
};

class CBinarySplitterFactory : public ISplitterFactory
{
public:
        ISplitter* CreateSplitter();
};

class CTxtSplitterFactory : public ISplitterFactory
{
public:
        ISplitter* CreateSplitter();
};

class CPictureISplitterFactory : public ISplitterFactory
{
public:
        ISplitter* CreateSplitter();
};

factory.cpp

#include "factory.h"
#include "imp.h"

ISplitter* CBinarySplitterFactory::CreateSplitter()
{
    return new BinarySplitter();
}

ISplitter* CTxtSplitterFactory::CreateSplitter()
{
    return new TxtSplitter();
}

ISplitter* CPictureISplitterFactory::CreateSplitter()
{
    return new PictureISplitter();
}

imp.h

#pragma once

class ISplitter
{
public:
        virtual void split() = 0;
        virtual ~ISplitter(){}
};

class BinarySplitter : public ISplitter
{
public:
    void split();
};

class TxtSplitter : public ISplitter
{
public:
    void split();
};

class PictureISplitter : public ISplitter
{
public:
    void split();
};

imp.cpp

#include <iostream>
#include "imp.h"

using namespace std;

void BinarySplitter::split()
{
    cout << "split BinarySplitter" << endl;
}

void TxtSplitter::split()
{
    cout << "split TxtSplitter" << endl;
}

void PictureISplitter::split()
{
    cout << "split PictureISplitter" << endl;
}

main.cpp

#include <cstdio>
#include <cstdlib>
#include "factory.h"
#include "imp.h"

class Fun
{
    ISplitterFactory* m_pFactory;
public:
    Fun(ISplitterFactory* factory)
    {
        m_pFactory = factory;
    }
    ~Fun(){}
    void test()
    {
        ISplitter *splitter = m_pFactory->CreateSplitter();
        splitter->split();
                delete splitter ;
                splitter = NULL;
    }
};

int main()
{
    //對象創建
    ISplitterFactory* factory = new CPictureISplitterFactory();
    
    //在form的內部factory只需要知道接口,不需要知道具體類型。在form內部並不知道factory的類型
    Fun form(factory);
    form.test();
    //這裏也只是依賴了facotory ,不關心factory的真實類型
    ISplitter *splitter = factory->CreateSplitter();
    splitter->split();
    delete splitter ;
    splitter = NULL;
    delete factory;
    factory = NULL;

    return 0;
}

優點:

  • 隔離了類對象的使用者和具體類型之間的耦合關系

缺點:

  • 不同對象的創建方法參數要相同,即不同工廠的CreateSplitter簽名需要一致。

工廠方法(虛構造器)