C++工厂方法模式:Factory Method Pattern

工厂(Factory)处理创建对象的细节,只负责创建对象。方便不同的对象需要时通过工厂来获取对象。

简单工厂其实不是一种设计模式,反而比较像是一种编程习惯。但是由于经常被使用,有些开发人员把这个编程习惯误认为是“工厂模式”。

简单工厂模式:实例化对象的时候不再使用 new Object()的形式,根据用户选择的产品类名或者某个标识来实例化具体的类。但是会业务扩展而使得简单工厂类数量庞大。

工厂方法模式:工厂方法模式是对简单工厂模式进一步的解耦,在工厂方法模式中是一类产品对应一个工厂类,而这些工厂类都继承于一个抽象工厂。这相当于是把原本会随着业务扩展而数量庞大的简单工厂类,分类成了一个个的具体产品工厂类,这样代码就不会都耦合在同一个类里。

工厂方法模式定义了一个创建对象的接口,但由子类决定要具体实现化的类是哪一个。工厂方法让类把实例化推迟到子类。

假设现在我们准备开一家披萨店,不同种类的披萨都有相同的一套制作流程:被准备、被烘烤、被切片、被装盒,但是不同的披萨有不同的口味和添加不同的配料比如cheese、veggie等。随着业务的扩展,来自不同地方的风味各异的披萨店准备来加盟,它们有不同的风味但是需要添加的配料还是相同。(后续扩展:实现一个原料工厂生产不同的原料:抽象工厂模式)

设计原则

依赖倒置原则:披萨店最开始的设计是一家披萨店直接生产各个具体的披萨类,这样导致披萨店(高层组件)过分依赖各个具体的披萨类(低层组件)。解决方法是抽象出一个Pizza类,让高层组件和低层组件都依赖于这个抽象类。

类图:

把变化和不变化的部分分离,把可能变化的具体披萨类的生产封装在一个工厂中。

由于Pizza对象是抽象的,orderPizza()并不知道哪些具体类参与进来了,换句话说,这就是解耦(decouple)。

加盟店有它的好处,可以从PizzaStore继承获得所有的功能。加盟店只需要继承PizzaStore,然后提供createPizza()方法实现自己的披萨风味即可。注意,超类的orderPizza()方法并不知道创建的披萨是哪一种,它只知道这个披萨可以被准备、被烘烤、被切片、被装盒。

缺点

当需要新增产品时,都必须要编写新的具体产品类,而且还要提供与之对应的具体工厂类,随着类的不断增加,在一定程度上增加了系统的复杂度,会有更多的类需要编译和加载,会给系统带来一些额外的开销。

实现如下:

pizzaStore.h:

#ifndef PIZZASTORE_H
#define PIZZASTORE_H
#include "pizza.h"

class PizzaStore {
public:
    virtual Pizza* orderPizza(string type) = 0;
    virtual Pizza* createPizza(string type) =  0;
};

#endif // PIZZASTORE_H

NYPizzaStore.h:

#ifndef NYPIZZASTORE_H
#define NYPIZZASTORE_H
#include "pizzaStore.h"
#include "NYStyleCheesePizza.h"

class NYPizzaStore : public PizzaStore {
public:
    virtual Pizza* orderPizza(string type) override;
    virtual Pizza* createPizza(string type) override;
};

Pizza* NYPizzaStore::createPizza(string type)
{
    Pizza* pizza;

    if(type == "cheese")
    {
        pizza = new NYStyleCheesePizza();
    }

    return pizza;
}

Pizza* NYPizzaStore::orderPizza(string type)
{
    Pizza* pizza;
    pizza = createPizza(type);
    pizza->prepare();
    pizza->bake();
    pizza->cut();
    pizza->box();

    return pizza;
}

#endif // NYPIZZASTORE_H

ChicagoPizzaStore.h:

#ifndef CHICAGOPIZZASTORE_H
#define CHICAGOPIZZASTORE_H
#include "pizzaStore.h"
#include "ChicagoStyleVeggiePizza.h"

class ChicagoPizzaStore : public PizzaStore {
public:
    virtual Pizza* orderPizza(string type) override;
    virtual Pizza* createPizza(string type) override;
};

Pizza* ChicagoPizzaStore::createPizza(string type)
{
    Pizza* pizza;

    if(type == "veggie")
    {
        pizza = new ChicagoStyleVeggiePizza();
    }

    return pizza;
}

Pizza* ChicagoPizzaStore::orderPizza(string type)
{
    Pizza* pizza;
    pizza = createPizza(type);
    pizza->prepare();
    pizza->bake();
    pizza->cut();
    pizza->box();

    return pizza;
}
#endif // CHICAGOPIZZASTORE_H

pizza.h:

#ifndef PIZZA_H
#define PIZZA_H
#include <iostream>
#include <string>
using namespace std;

class Pizza {
public:
    void prepare();
    void bake();
    void cut();
    void box();
    void display();

protected:
    string m_type;
};

void Pizza::prepare()
{
    cout << "准备,";
}

void Pizza::bake()
{
    cout << "烘烤,";
}

void Pizza::cut()
{
    cout << "切片,";
}

void Pizza::box()
{
    cout << "装箱,";
}

void Pizza::display()
{
    cout << m_type << "制作好了!" << endl;
}
#endif // PIZZA_H

NYStyleCheesePizza.h:

#ifndef NYSTYLECHEESEPIZZA_H
#define NYSTYLECHEESEPIZZA_H
#include "pizza.h"

class NYStyleCheesePizza : public Pizza {
public:
    NYStyleCheesePizza();
};

NYStyleCheesePizza::NYStyleCheesePizza()
{
    m_type = "纽约奶酪披萨";
}

#endif // NYSTYLECHEESEPIZZA_H


ChicagoStyleVeggiePizza.h:

#ifndef CHICAGOSTYLEVEGGIEPIZZA_H
#define CHICAGOSTYLEVEGGIEPIZZA_H
#include "pizza.h"

class ChicagoStyleVeggiePizza : public Pizza {
public:
    ChicagoStyleVeggiePizza();
};

ChicagoStyleVeggiePizza::ChicagoStyleVeggiePizza()
{
    m_type = "芝加哥蔬菜披萨";
}

#endif // CHICAGOSTYLEVEGGIEPIZZA_H

main.cpp:

/*
 * 工厂方法模式
 *
 * date:2023-9-8
*/

#include "NYPizzaStore.h"
#include "ChicagoPizzaStore.h"

int main()
{
    cout << "订购一个纽约风味的奶酪披萨" << endl;
    PizzaStore *pizzaStore = new NYPizzaStore();
    Pizza *pizza = pizzaStore->orderPizza("cheese");
    pizza->display();

    cout << "\n芝加哥风味的披萨店加盟,可以订购芝加哥风味的披萨了\n" << endl;

    cout << "订购一个芝加哥风味的蔬菜披萨" << endl;
    pizzaStore = new ChicagoPizzaStore();
    pizza = pizzaStore->orderPizza("veggie");
    pizza->display();
}

运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值