Add abstract-factory pattern example

This commit is contained in:
Shaun Reed 2021-05-11 15:42:08 -04:00
parent 54426cbe5b
commit baabfa439a
6 changed files with 225 additions and 0 deletions

View File

@ -0,0 +1,21 @@
###############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ##
## About: A project for practicing the abstract factory C++ design pattern ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
#
cmake_minimum_required(VERSION 3.15)
project(
#[[NAME]] AbstractFactory
VERSION 1.0
DESCRIPTION "An example of the abstract factory design pattern in C++"
LANGUAGES CXX
)
add_compile_options("-Wall")
add_library(parts "parts.cpp")
add_library(abstract-factory "factory.cpp")
add_executable(abstract-factory-test "main.cpp")
target_link_libraries(abstract-factory-test abstract-factory parts)

View File

@ -0,0 +1,60 @@
#ifndef FACTORY_HPP
#define FACTORY_HPP
#include <array>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "parts.hpp"
class AbstractFactory {
public:
AbstractFactory(std::string name_): name(std::move(name_)) {}
virtual ~AbstractFactory() = default;
Part* requestPart();
Part* requestPart(std::string partName, float price);
void showStock() const;
std::string getName() const { return name;}
protected:
virtual Part* makePart() = 0;
virtual Part* makePart(std::string name, float price) = 0;
private:
std::string name;
std::unordered_map<std::string, int> inventory;
};
/*****************************************************************************/
// Gear Concrete Factory
class GearFactory : public AbstractFactory {
public:
explicit GearFactory(std::string name_="GearFactory") :
AbstractFactory(std::move(name_)) {}
protected:
Part* makePart() override;
Part* makePart(std::string name, float price);
};
/*****************************************************************************/
// Spring Concrete Factory
class SpringFactory : public AbstractFactory {
public:
explicit SpringFactory (std::string name_="SpringFactory"):
AbstractFactory(std::move(name_)) {}
protected:
Part* makePart() override;
Part* makePart(std::string name, float price);
};
#endif // FACTORY_HPP

View File

@ -0,0 +1,55 @@
#include <iostream>
#include "abstract-factory.hpp"
Part* AbstractFactory::requestPart() {
// Create a new part
Part * newPart = makePart();
// Increment the QTY for part in AbstractFactory::inventory base class
// + If the item is not in the inventory map, this will also add it first.
inventory[newPart->getName()]++;
// Make the requested part
return newPart;
}
Part* AbstractFactory::requestPart(std::string partName, float price)
{
Part * newPart = makePart(partName, price);
inventory[newPart->getName()]++;
return newPart;
}
void AbstractFactory::showStock() const
{
for (const auto &item : inventory) {
if (item.first.empty()) continue; // Don't show an empty item
std::cout << item.first << " QTY in stock: " << item.second << std::endl;
}
}
/*****************************************************************************/
// Gear
Part* GearFactory::makePart() {
return new Gear();
}
Part* GearFactory::makePart(std::string name, float price)
{
return new Gear(name, price);
}
/*****************************************************************************/
// Spring
Part* SpringFactory::makePart() {
return new Spring();
}
Part *SpringFactory::makePart(std::string name, float price)
{
return new Spring(name, price);
}

View File

@ -0,0 +1,35 @@
#include <array>
#include <cstdlib>
#include <iostream>
#include <vector>
#include "abstract-factory.hpp"
int main(const int argc, const char * argv[]) {
// Testing GearFactory
GearFactory gearFactory;
const int gearsRequired = 5;
std::cout << "Testing " << gearFactory.getName() <<"...\nMaking 5 Gears...\n";
for (int i = 0; i < gearsRequired; i++) gearFactory.requestPart();
std::cout << std::endl << gearFactory.getName() << " inventory:\n";
gearFactory.showStock();
// Testing SpringFactory
SpringFactory springFactory;
const int springsRequired = 5;
for (int i = 0; i < springsRequired; i++) springFactory.requestPart();
std::cout << std::endl << springFactory.getName() << " inventory:\n";
springFactory.showStock();
// Making custom gears and springs
for (int i = 0; i < gearsRequired; i++) gearFactory.requestPart("Big Gear", 2.5f);
std::cout << std::endl << gearFactory.getName() << " inventory:\n";
gearFactory.showStock();
for (int i = 0; i < springsRequired; i++) springFactory.requestPart("Big Spring", 5.0f);
std::cout << std::endl << springFactory.getName() << " inventory:\n";
springFactory.showStock();
}

View File

@ -0,0 +1,19 @@
#include "parts.hpp"
/*****************************************************************************/
// Gear
Gear::Gear(std::string name, float price) {
partName = name;
partPrice = price;
}
/*****************************************************************************/
// Spring
Spring::Spring(std::string name, float price) {
partName = name;
partPrice = price;
}

View File

@ -0,0 +1,35 @@
#ifndef PARTS_HPP
#define PARTS_HPP
#include <string>
class Part {
public:
std::string getName() const { return partName;}
float getPrice() const { return partPrice;}
protected:
std::string partName; // The name of the part
float partPrice; // The partPrice of the part
};
/*****************************************************************************/
// Gear
class Gear : public Part {
public:
Gear(std::string name="Gear", float price = 1.0f);
};
/*****************************************************************************/
// Spring
class Spring : public Part {
public:
Spring(std::string name = "Spring", float price = 2.0f);
};
#endif // PARTS_HPP