日常我们开发的过程中,有时候需要用到一些只需要定义接口,然后让子类去决定实例化哪个类的情况,就可以用到我们所说的工厂方法(Factory Method)来解决这个问题,那么Factory模式的作用,可以给出如下的定义:
Factory模式可以用来定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法(Factory Method)可以使一个类的实例化过程延迟到子类中再进行。
从上述UML结构图可以看出:
从上述解释不难看出:在这个模式中,有两个抽象基类,一个是 Product 为创建出来的对象的抽象基类,一个是 Factory 是工厂的抽象基类,在互相协作的时候都是由相应的 Factory 派生类来生成Product的派生类,也就是说如果要新增一种Product那么也要对应的新增一个 Factory,创建的过程委托给了这个 Factory。也就是说一个 Factory和一个 Product 是一一对应的关系。
本代码是我在Qt项目和我自己的一些基础库项目的基础上编写的一个简单的设计模式学习演示的Demo,具体的一些往期文章可以参考:
通过对上述概念的理解,我个人编写了如下的代码:
basic_factory_pattern.h
///
// Copyright (c)2021, Tom Zhao personal. ("TZOpenTools")
// This software is a personal tools project by Tom Zhao.
// Description:
///
#ifndef _BASIC_FACTORY_PATTERN_H_H_
#define _BASIC_FACTORY_PATTERN_H_H_
#include "zsofts_compiler_specific.h"
TZ_NAMESPACE_BEGIN(TzSoft)
class TzFactoryPatternProduct
{
public:
TzFactoryPatternProduct()
{
}
virtual ~TzFactoryPatternProduct()
{
}
};
class TzFactoryPattrenConcreateProduct : public TzFactoryPatternProduct
{
public:
TzFactoryPattrenConcreateProduct();
virtual ~TzFactoryPattrenConcreateProduct();
};
class TzFactoryPattrenCreator
{
public:
TzFactoryPattrenCreator()
{
}
virtual ~TzFactoryPattrenCreator()
{
}
void anOperatrion();
protected:
virtual TzFactoryPatternProduct* FactoryMeghod() = 0;
};
class TzFactoryPattrenConcreateCreator : public TzFactoryPattrenCreator
{
public:
TzFactoryPattrenConcreateCreator();
virtual ~TzFactoryPattrenConcreateCreator();
protected:
virtual TzFactoryPatternProduct* FactoryMeghod();
};
TZ_NAMESPACE_END(TzSoft)
#endif
basic_factory_pattern.cpp
///
// Copyright (c)2021, Tom Zhao personal. ("TZOpenTools")
// This software is a personal tools project by Tom Zhao.
// Description:
///
#include "basic_factory_pattern.h"
#include
TZ_NAMESPACE_BEGIN(TzSoft)
TzFactoryPattrenConcreateProduct::TzFactoryPattrenConcreateProduct()
{
qDebug() << " construction of ConcreateProduct";
}
TzFactoryPattrenConcreateProduct::~TzFactoryPattrenConcreateProduct()
{
qDebug() << " construction of ConcreateProduct";
}
void TzFactoryPattrenCreator::anOperatrion()
{
TzFactoryPatternProduct* p = FactoryMeghod();
qDebug() << " an operation of product";
}
TzFactoryPattrenConcreateCreator::TzFactoryPattrenConcreateCreator()
{
qDebug() << " construction of ConcreateCreator";
}
TzFactoryPattrenConcreateCreator::~TzFactoryPattrenConcreateCreator()
{
qDebug() << " destruction of ConcreateCreator";
}
TzFactoryPatternProduct* TzFactoryPattrenConcreateCreator::FactoryMeghod()
{
return new TzFactoryPattrenConcreateProduct();
}
TZ_NAMESPACE_END(TzSoft)
咱们在编写代码的时候,自然有一个好习惯和优良传统就是没事可以给自己编写一些测试代码,让自己的代码更加健壮和更加完备,因此我自己编写了一些简单的测试代码:
basic_factory_pattern_ctests.h
///
// Copyright (c)2021, Tom Zhao personal. ("TZOpenTools")
// This software is a personal tools project by Tom Zhao.
// Description:
///
#ifndef _BASIC_FACTORY_PATTERN_CTEST_H_H_
#define _BASIC_FACTORY_PATTERN_CTEST_H_H_
#include "basic_factory_pattern.h"
TZ_NAMESPACE_BEGIN(TzSoftTest)
class TzFactoryTest
{
public:
static void testCase_01(void);
};
TZ_NAMESPACE_END(TzSoftTest)
#endif
basic_factory_pattern_ctests.cpp
///
// Copyright (c)2021, Tom Zhao personal. ("TZOpenTools")
// This software is a personal tools project by Tom Zhao.
// Description:
///
#include "basic_factory_pattern_ctests.h"
#include
TZ_NAMESPACE_BEGIN(TzSoftTest)
void TzFactoryTest::testCase_01(void)
{
TzSoft::TzFactoryPattrenCreator* p = new TzSoft::TzFactoryPattrenConcreateCreator();
p->anOperatrion();
delete p;
p = nullptr;
qDebug() << "TzFactoryTest::testCase_01 end!";
return;
}
TZ_NAMESPACE_END(TzSoftTest)
main.cpp
///
// Copyright (c)2021, Tom Zhao personal. ("TZOpenTools")
// This software is a personal tools project by Tom Zhao.
// Description:
///
#include "basic_factory_pattern_ctests.h"
#include "basic_abstract_factory_pattern_ctests.h"
#include "basic_builder_pattern_ctests.h"
#include "basic_prototype_pattern_ctests.h"
#include "basic_singleton_pattern_ctests.h"
#include "basic_adapter_pattern_ctests.h"
#include "basic_bridge_pattern_ctests.h"
#include "basic_composite_pattern_ctests.h"
#include "basic_decorator_pattern_ctests.h"
#include "basic_proxy_pattern_ctests.h"
#include "basic_template_method_pattern_ctests.h"
#include "basic_chain_of_responsibility_pattern_ctests.h"
#include "basic_flyweight_pattern_ctests.h"
#include "basic_command_pattern_ctests.h"
#include "basic_observer_pattern_ctests.h"
#include "basic_strategy_pattern_ctests.h"
#include "basic_state_pattern_ctests.h"
#include "basic_iterator_pattern_ctests.h"
#include "basic_memento_pattern_ctests.h"
#include "basic_visitor_pattern_ctests.h"
#include
#include
void testQStringTr()
{
QString str("Hello , this is a test.");
qDebug() << QObject::tr(str.toStdString().c_str());
}
void testPFunc(int* p)
{
delete p;
p = nullptr;
}
void testDeleteOut()
{
int* p = new int;
*p = 10;
qDebug() << p << "\t" << *p;
testPFunc(p);
// delete p;
qDebug() << p << "\t" << *p;
*p = 20;
qDebug() << p << "\t" << *p;
}
typedef struct TestUsing
{
int m_a = {
0 };
int m_b = {
1 };
float m_f = {
0.0f };
} UTest, UTT;
using UsingTT = struct TestU
{
int m_a = {
0 };
int m_b = {
1 };
float m_f = {
0.0f };
};
void testUsingPrint(void)
{
UsingTT tt;
UTest ut;
qDebug() << tt.m_a << '\t' << tt.m_b << '\t' << tt.m_f;
qDebug() << ut.m_a << '\t' << ut.m_b << '\t' << ut.m_f;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
#if 1
qDebug() << "This is the Factory Pattern Tests:";
TzSoftTest::TzFactoryTest::testCase_01();
qDebug() << "This is the Abstract Factory Pattern Tests:";
TzSoftTest::TzAbstractFactoryTest::testCase_01();
qDebug() << "This is the Builder Pattern Tests:";
TzSoftTest::TzBuilderTest::testCase_01();
qDebug() << "This is the Prototype Pattern Tests:";
TzSoftTest::TzPrototypeTest::testCase_01();
qDebug() << "This is the Singleton Pattern Tests:";
TzSoftTest::TzSingletonTest::testCase_01();
qDebug() << "This is the Adapter01 Pattern Tests:";
TzSoftTest::TzAdapter01Test::testCase_01();
qDebug() << "This is the Bridge Pattern Tests:";
TzSoftTest::TzBridgeTest::testCase_01();
qDebug() << "This is the Composite Pattern Tests:";
TzSoftTest::TzCompositeTest::testCase_01();
qDebug() << "This is the Decorator Pattern Tests:";
TzSoftTest::TzDecoratorTest::testCase_01();
qDebug() << "This is the Proxy Pattern Tests:";
TzSoftTest::TzProxyTest::testCase_01();
qDebug() << "This is the Template Method Pattern Tests:";
TzSoftTest::TzTemplateMethodTest::testCase_01();
qDebug() << "This is the Chain of Responsibility Pattern Tests:";
TzSoftTest::TzChainOfResponsibilityTest::testCase_01();
qDebug() << "This is the Flyweight Pattern Tests:";
TzSoftTest::TzFlyweightTest::testCase_01();
qDebug() << "This is the Command Pattern Tests:";
TzSoftTest::TzCommandTest::testCase_01();
qDebug() << "This is the Observer Pattern Tests:";
TzSoftTest::TzObserverTest::testCase_01();
qDebug() << "This is the Strategy Pattern Tests:";
TzSoftTest::TzStrategyTest::testCase_01();
qDebug() << "This is the State Pattern Tests:";
TzSoftTest::TzStateTest::testCase_01();
qDebug() << "This is the Iterator Pattern Tests:";
TzSoftTest::TzIteratorTest::testCase_01();
qDebug() << "This is the Memento Pattern Tests:";
TzSoftTest::TzMementoTest::testCase_01();
qDebug() << "This is the Visitor Pattern Tests:";
TzSoftTest::TzVisitorTest::testCase_01();
testDeleteOut();
testUsingPrint();
#endif
testQStringTr();
return a.exec();
}
通过上述过程可以看出来,一个创建者先构造自己之后再去创建子类完成之后,就可以对子类进行操作了,这样对外其实我们操作的是创建者,不需要关心是什么子类来实现的过程。
用心去感受你自己需要坚持的生活,未来慢慢会给你答案的。