Factory_Pattern_2 - 8BitsCoding/RobotMentor GitHub Wiki

๋ชฉ์ฐจ


(Factory Method) ํ•œ ์ ์„ ๋ฐ›๋Š” ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์ž.

cartesian, polar๋กœ ์ ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ƒ์„ฑ์ž๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผํ• ๊นŒ?

enum class PointType
{
    cartesian,
    polar
};

struct Point 
{
    //Point(float x, float y) : x(x), y(y) {}

    // param a this is either x or rho
    // param b this is either y or theta
    // param type 
    Point(float a, float b, PointType type = PointType::cartesian)
    {
        if(type == PointType::cartesian)
        {
            x = a;
            y = b;
        } else {
            x = a * cos(b);
            y = a * sin(b);
        }
    }

    float x, y;
};

int main()
{
    return 0;
}

ํ ... ์ด๊ฒŒ ๊ณผ์—ฐ ์ตœ์„ ์ธ๊ฐ€? ์ƒ์„ฑ์ž์— ๋งค๋ฒˆ cartesian, polar์“ธ์ง€ ์ ์–ด์ฃผ๋Š”๊ฒŒ ์ตœ์„ ์ธ๊ฐ€?


(Factory Method) ์ „์ฒด์ฝ”๋“œ

์ด๋Ÿฐ ์ฝ”๋“œ๋Š” ์–ด๋–จ๊นŒ? ์ƒ์„ฑ์ž ์ž์ฒด์—์„œ cartesian, polar๋ฅผ ์„ ํƒํ•˜๊ฒŒ ํ•ด๋ณด์ž.

#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>

enum class PointType
{
  cartesian,
  polar
};

class Point
{
  /*Point(float a, float b, PointType type = PointType::cartesian)
  {
  if (type == PointType::cartesian)
  {
  x = a; b = y;
  }
  else
  {
  x = a*cos(b);
  y = a*sin(b);
  }
  }*/


  Point(const float x, const float y)
    : x{x},
      y{y}
  {
  }

public:
  float x, y;


  friend std::ostream& operator<<(std::ostream& os, const Point& obj)
  {
    return os
      << "x: " << obj.x
      << " y: " << obj.y;
  }

  static Point NewCartesian(float x, float y)
  {
    return{ x,y };
  }
  static Point NewPolar(float r, float theta)
  {
    return{ r*cos(theta), r*sin(theta) };
  }
};

int main_z()
{
  // will not work
  //Point p{ 1,2 };

  auto p = Point::NewPolar(5, M_PI_4);
  std::cout << p << std::endl;

  getchar();
  return 0;
}

Factory ๊ตฌํ˜„ ์ „์ฒด์ฝ”๋“œ

Method๋ณด๋‹ค ์ด๋Ÿฐ๋ฐฉ์‹์„ ์„ ํ˜ธํ•œ๋‹ค.

#include <cmath>

enum class PointType
{
  cartesian,
  polar
};

class Point
{
  /*Point(float a, float b, PointType type = PointType::cartesian)
  {
    if (type == PointType::cartesian)
    {
      x = a; b = y;
    } 
    else
    {
      x = a*cos(b);
      y = a*sin(b);
    }
  }*/

  // use a factory method
  Point(float x, float y) : x(x), y(y){}
public:
  float x, y;

  friend class PointFactory;
};

class PointFactory
{
  static Point NewCartesian(float x, float y)
  {
    return Point{ x,y };
  }

  static Point NewPolar(float r, float theta)
  {
    return Point{ r*cos(theta), r*sin(theta) };
  }
};

int main()
{
    auto p = PointFacory::NewPolar(5, M_PI_4);
    cout << p << endl;

    return 0;
}

Inner Factory

#include <cmath>

// do not need this for factory
enum class PointType
{
  cartesian,
  polar
};

class Point
{
  /*Point(float a, float b, PointType type = PointType::cartesian)
  {
  if (type == PointType::cartesian)
  {
  x = a; b = y;
  }
  else
  {
  x = a*cos(b);
  y = a*sin(b);
  }
  }*/

  // use a factory method
  Point(float x, float y) : x(x), y(y) {}

  class PointFactory
  {
    PointFactory() {}
  public:
    static Point NewCartesian(float x, float y)
    {
      return { x,y };
    }
    static Point NewPolar(float r, float theta)
    {
      return{ r*cos(theta), r*sin(theta) };
    }
  };
public:
  float x, y;
  static PointFactory Factory;
};

int main_2()
{
  // will not work
  // Point p{ 1,2 };

  // nope!
  // Point::PointFactory pf;

  // if factory is public, then
  //auto p = Point::PointFactory::NewCartesian(3, 4);

  // at any rate, use this
  auto pp = Point::Factory.NewCartesian(2, 3);

  return 0;
}

Abstract Factory

// AbstractFactory.cpp
#include <iostream>
#include <memory>
#include <map>
#include "HotDrink.h"
#include "DrinkFactory.h"
using namespace std;

unique_ptr<HotDrink> make_drink(string type)
{
  unique_ptr<HotDrink> drink;
  if (type == "tea")
  {
    drink = make_unique<Tea>();
    drink->prepare(200);
  }
  else 
  {
    drink = make_unique<Coffee>();
    drink->prepare(50);
  }
  return drink;
}

int main53()
{
  auto d = make_drink("tea");

  DrinkFactory df;
  df.make_drink("coffee");

  getchar();
  return 0;
}
// DrinkFactory.h
#pragma once
#include <string>
#include "HotDrink.h"
#include "TeaFactory.h"
#include "CoffeeFactory.h"
#include <map>
#include <functional>

struct HotDrink;

class DrinkFactory
{
  map<string, unique_ptr<HotDrinkFactory>> hot_factories;
public:
  DrinkFactory()
  {
    hot_factories["coffee"] = make_unique<CoffeeFactory>();
    hot_factories["tea"] = make_unique<TeaFactory>();
  }

  unique_ptr<HotDrink> make_drink(const string& name)
  {
    auto drink = hot_factories[name]->make();
    drink->prepare(200); // oops!
    return drink;
  }
};

class DrinkWithVolumeFactory
{
  map<string, function<unique_ptr<HotDrink>()>> factories;
public:

  DrinkWithVolumeFactory()
  {
    factories["tea"] = [] {
      auto tea = make_unique<Tea>();
      tea->prepare(200);
      return tea;
    };
  }

  unique_ptr<HotDrink> make_drink(const string& name);
};

inline unique_ptr<HotDrink> DrinkWithVolumeFactory::make_drink(const string& name)
{
  return factories[name]();
}
// HotDrinkFactory.h
#pragma once
#include "HotDrink.h"

struct HotDrinkFactory
{
  virtual unique_ptr<HotDrink> make() const = 0;
};
// CoffeeFactory.h
#pragma once
#include <memory>
#include "HotDrink.h"
#include "HotDrinkFactory.h"

struct HotDrink;

struct CoffeeFactory : HotDrinkFactory
{
  unique_ptr<HotDrink> make() const override
  {
    return make_unique<Coffee>();
  }
};
// HotDrink.h
#pragma once
#include <memory>
#include <map>
#include <string>
using namespace std;

struct HotDrink
{
  virtual ~HotDrink() = default;

  virtual void prepare(int volume) = 0;
};

struct Tea : HotDrink
{

  void prepare(int volume) override
  {
    cout << "Take tea bag, boil water, pour " << volume << "ml, add some lemon" << endl;
  }
};

struct Coffee : HotDrink
{
  void prepare(int volume) override
  {
    cout << "Grind some beans, boil water, pour " << volume << "ml, add cream, enjoy!" << endl;
  }
};
โš ๏ธ **GitHub.com Fallback** โš ๏ธ