(C++设计模式) —— 常见设计模式学习笔记 - Factory模式(工厂)

常见设计模式学习笔记 - Factory模式

概述

基本概念

     日常我们开发的过程中,有时候需要用到一些只需要定义接口,然后让子类去决定实例化哪个类的情况,就可以用到我们所说的工厂方法(Factory Method)来解决这个问题,那么Factory模式的作用,可以给出如下的定义:

     Factory模式可以用来定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法(Factory Method)可以使一个类的实例化过程延迟到子类中再进行。

     UML 结构图:
在这里插入图片描述

UML图解释

     从上述UML结构图可以看出:

  • 抽象基类:
    1. Product:创建出来的对象的抽象基类。
    2. Factory 创建对象的工厂方法的抽象基类。
  • 接口函数
    1. Creator::FactoryMethod:纯虚函数,由派生类实现,创建出对应的 Product。

     从上述解释不难看出:在这个模式中,有两个抽象基类,一个是 Product 为创建出来的对象的抽象基类,一个是 Factory 是工厂的抽象基类,在互相协作的时候都是由相应的 Factory 派生类来生成Product的派生类,也就是说如果要新增一种Product那么也要对应的新增一个 Factory,创建的过程委托给了这个 Factory。也就是说一个 Factory和一个 Product 是一一对应的关系。

编写代码

环境概要

     本代码是我在Qt项目和我自己的一些基础库项目的基础上编写的一个简单的设计模式学习演示的Demo,具体的一些往期文章可以参考:

  1. C++ 技巧分享 —— 定义一些测试宏来区分正常逻辑代码和编写中间过程中希望加入的测试代码
  2. C++ 项目成长 ——自定义数据类型,定义各种类型别名, typedef的部分用法实例
  3. C++ 项目成长 —— 重定义一些自己平台关于字符串的系统操作
  4. C++ 项目成长 —— 自定义平台的定位追踪器
  5. C++ 项目成长 —— 自定义自己平台的Asserter工具的宏定义
  6. Visual Studio 技巧分享 —— 用户自定义宏和给项目添加宏预处理
  7. Qt 杂记 —— Qt安装并配置调试文件,添加源码调试pdb文件

具体代码

     通过对上述概念的理解,我个人编写了如下的代码:

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 <QtCore/QDebug>

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 <QtCore/QDebug>

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 <QtCore/QCoreApplication>
#include <QtCore/QDebug>

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();
}

小结

     通过上述代码的运行,可以得到下面的运行效果:
在这里插入图片描述

     通过上述过程可以看出来,一个创建者先构造自己之后再去创建子类完成之后,就可以对子类进行操作了,这样对外其实我们操作的是创建者,不需要关心是什么子类来实现的过程。

个人格言

    用心去感受你自己需要坚持的生活,未来慢慢会给你答案的。

在这里插入图片描述

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值