Prototype_Pattern_2 - 8BitsCoding/RobotMentor GitHub Wiki

목차


Record Keeping

struct Address
{
  string street;
  string city;
  int suite;
};

struct Contact
{
  string name;
  Address* address;
};

int main() 
{
    Contact john = {"john doe", Address{{"123 East Dr"},{"London"},123}};
    Contact jane = {"jane smith", Address{{"123 East Dr"},{"London"},103}};
}

매번 멤버가 추가될때 저런식으로 한줄씩 너어야 할까?

Contact john = {"john doe", Address{{"123 East Dr"},{"London"},123}};
Contact jane = john;
jane.name = "jane smith";
jane->address.suite = 123;

위 방식의 문제는 누군가 이렇게 쓸때 이다.

Contact john = {"john doe", new Address{{"123 East Dr"},{"London"},123}};
Contact jane = john;
jane.name = "jane smith";
jane.address->suite = 123;

돌려보면 알겠지만 john과 jane이 같은 방에 살게된다.


Prototype

위 문제를 Copy contructor를 생성해서 막아보자.

// struct Contact
Contact(const Contact& other)
    : name {other.name}
    , address {new Address{other.address->street, other.address->city, other.address->suite}}
{
}

// main
Contact john = {"john doe", new Address{{"123 East Dr"},{"London"},123}};
Contact jane{john};
jane.name = "jane smith";
jane.address->suite = 123;

같은 방에 사는 문제가 해결된다.

Address도 좀 더 최적화 할 수 있을거 같은데?

// struct Address
Address(const Address& address) 
    : street{address.street}, city{address.city}, suite{address.suite}
{
}

// struct Contact
Contact(const Contact& other)
    : name {other.name}
    , address {new Address{*other.address}}
{
}

// main
Contact john = {"john doe", new Address{{"123 East Dr"},{"London"},123}};
Contact jane{john};
jane.name = "jane smith";
jane.address->suite = 123;

Prototype Factory

Factory를 통해서 좀 더 쉽게 만들어 보자.

struct EmployeeFactory
{
    static unique_ptr<Contack> new_main_office_employee(const string& name, const int suite)
    {
        static Contact p{"", new Address{"123 East Dr", "London", 0}};
        return new_employee(name, suite, p);
    }

private:
    static unique_ptr<Contact> new_employee(const string& name, int suite, const Contact& prototype) 
    {
        auto result = make_unique<Contact>(prototype);
        result->name = name;
        result->address->suite = suite;
        return result;
    }
}

int main()
{
    auto john = EmployeeFactory::new_main_office_employee("Jogn", 123);
}

Prototype via Serialization

내가 Serialization을 쓰지 않아서 정리하지 않음

boost의 serialization과 관련된 내용


전체코드

#include <string>
#include <iostream>
#include <memory>
#include <functional>
#include <sstream>
#include "Person.h"
using namespace std;
#include <boost/serialization/serialization.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

struct Address
{
  string street;
  string city;
  int suite;


  Address(const string& street, const string& city, const int suite)
    : street{street},
      city{city},
      suite{suite}
  {
  }

  /*Address(const Address& other)
    : street{other.street},
      city{other.city},
      suite{other.suite}
  {
  }*/

  friend ostream& operator<<(ostream& os, const Address& obj)
  {
    return os
      << "street: " << obj.street
      << " city: " << obj.city
      << " suite: " << obj.suite;
  }
};


struct Contact
{
  string name;
  Address* address;

  Contact& operator=(const Contact& other)
  {
    if (this == &other)
      return *this;
    name = other.name;
    address = other.address;
    return *this;
  }

  Contact() : name(nullptr), address(nullptr)
  {} // required for serialization

  Contact(string name, Address* address)
    : name{name}, address{address}
  {
    //this->address = new Address{ *address };
  }

  Contact(const Contact& other)
    : name{other.name}
    //, address{ new Address{*other.address} }
  {
    address = new Address(
      other.address->street, 
      other.address->city, 
      other.address->suite
    );
  }


private:
  friend class boost::serialization::access;

  template <class archive>
  void save(archive& ar, const unsigned version) const
  {
    ar << name;
    ar << address;
  }

  template <class archive>
  void load(archive& ar, const unsigned version)
  {
    ar >> name;
    ar >> address;
  }

  BOOST_SERIALIZATION_SPLIT_MEMBER()

public:
  ~Contact()
  {
    delete address;
  }


  friend ostream& operator<<(ostream& os, const Contact& obj)
  {
    return os
      << "name: " << obj.name
      << " works at " << *obj.address; // note the star here
  }
};

struct EmployeeFactory
{
  static Contact main;
  static Contact aux;

  static unique_ptr<Contact> NewMainOfficeEmployee(string name, int suite)
  {
    //static Contact p{ "", new Address{ "123 East Dr", "London", 0 } };
    return NewEmployee(name, suite, main);
  }

  static unique_ptr<Contact> NewAuxOfficeEmployee(string name, int suite)
  {
    return NewEmployee(name, suite, aux);
  }

private:
  static unique_ptr<Contact> NewEmployee(string name, int suite, Contact& proto)
  {
    auto result = make_unique<Contact>(proto);
    result->name = name;
    result->address->suite = suite;
    return result;
  }
};

//Contact EmployeeFactory::main{ "", new Address{ "123 East Dr", "London", 0 } };
//Contact EmployeeFactory::aux{ "", new Address{ "123B East Dr", "London", 0 } };

int main_3423()
{
  // this is tedious
  // Contact john{ "John Doe", new Address{"123 East Dr", "London"} };
  // Contact jane{ "Jane Doe", new Address{"123 East Dr", "London"} };

  auto addr = new Address{ "123 East Dr", "London", 0 /* ? */ };

  //Contact john{ "John Doe", addr };
  //john.address->suite = 123;
  //Contact jane{ "Jane Doe", addr };
  //jane.address->suite = 124;

  //Contact jane2{ jane }; // shallow copy
  //jane2.address->suite = 555;

  

  //
  //std::cout << jane2 << std::endl;

  // whenever an address is needed, make a copy
  /*Contact john{ "John Doe", new Address{*addr} };
  john.address->suite = 123;

  Contact jane{ "Jane Doe", new Address{*addr} };
  jane.address->suite = 125;

  cout << john << "\n" << jane << endl;*/

  // much better. let's list employees
  //Contact employee{ "Unknown", new Address{"628 Happy St", "Joy", 0} };

  //// we can use this prototype to create john and jane
  //Contact john{ employee };
  //john.name = "John Doe";
  //john.address->suite = 123;

  //Contact jane{ employee };
  //jane.name = "Jane Doe";
  //jane.address->suite = 125;

  //cout << john << "\n" << jane << "\n";

  //delete addr;

  // 4. Boost Serialization

  // too much work in getting the copying working
  

  //auto john = EmployeeFactory::NewAuxOfficeEmployee("John Doe", 123);
  //auto jane = EmployeeFactory::NewMainOfficeEmployee("Jane Doe", 125);

  //cout << *john << "\n" << *jane << "\n"; // note the stars here

  delete addr;

  getchar();
  return 0;
}
⚠️ **GitHub.com Fallback** ⚠️