En ingeniería de software, los patrones de diseño creacional se ocupan de los mecanismos de creación de objetos, tratando de crear objetos de una manera adecuada a la situación. La forma básica u ordinaria de creación de objetos podría dar lugar a problemas de diseño o complejidad añadida al diseño. Builder Design Pattern en C++ resuelve este problema específico al separar la construcción de un objeto complejo de su representación .
Por cierto, si no ha consultado mis otros artículos sobre patrones de diseño creativo, aquí está la lista:
Los fragmentos de código que ve a lo largo de esta serie de artículos son simplificados, no sofisticados. Por lo tanto, a menudo me ve sin usar palabras clave como anular, final, público (mientras se hereda) solo para hacer que el código sea compacto y consumible (la mayoría de las veces) en un tamaño de pantalla estándar único. También prefiero struct en lugar de class solo para guardar la línea al no escribir "public:" a veces y también pierdo virtual destructor , constructor, copy constructor , prefix std::, eliminando la memoria dinámica, intencionalmente.
También me considero una persona pragmática que quiere transmitir una idea de la manera más simple posible en lugar de la forma estándar o el uso de jergas.
Nota:
Para crear/crear instancias de objetos complejos y complicados por partes y de manera sucinta al proporcionar una API en una entidad separada.
// <p>hello</p> auto text = "hello" ; string output; output += "<p>" ; output += text; output += "</p>" ; printf ( "<p>%s</p>" , text); // <ul><li>hello</li><li>world</li></ul> string words[] = { "hello" , "world" }; ostringstream oss; oss << "<ul>" ; for ( auto w : words) oss << " <li>" << w << "</li>" ; oss << "</ul>" ; printf (oss.str().c_str());
class HtmlBuilder ; class HtmlElement { string m_name; string m_text; vector <HtmlElement> m_childs; constexpr static size_t m_indent_size = 4 ; HtmlElement() = default ; HtmlElement( const string &name, const string &text) : m_name(name), m_text(text) {} friend class HtmlBuilder ; public : string str ( int32_t indent = 0 ) { ostringstream oss; oss << string (m_indent_size * indent, ' ' ) << "<" << m_name << ">" << endl ; if (m_text.size()) oss << string (m_indent_size * (indent + 1 ), ' ' ) << m_text << endl ; for ( auto &element : m_childs) oss << element.str(indent + 1 ); oss << string (m_indent_size * indent, ' ' ) << "</" << m_name << ">" << endl ; return oss.str(); } static unique_ptr <HtmlBuilder> build( string root_name) { return make_unique<HtmlBuilder>(root_name); } }; class HtmlBuilder { HtmlElement m_root; public : HtmlBuilder( string root_name) { m_root.m_name = root_name; } HtmlBuilder * add_child ( string child_name, string child_text) { m_root.m_childs.emplace_back(HtmlElement{child_name, child_text}); return this ; } string str () { return m_root.str(); } operator HtmlElement () { return m_root; } }; int main () { auto builder = HtmlElement::build( "ul" ); builder->add_child( "li" , "hello" )->add_child( "li" , "world" ); cout << builder->str() << endl ; return EXIT_SUCCESS; } /* <ul> <li> hello </li> <li> world </li> </ul> */
Persona.h
# pragma once # include <iostream> using namespace std ; class PersonBuilder ; class Person { std :: string m_name, m_street_address, m_post_code, m_city; // Personal Detail std :: string m_company_name, m_position, m_annual_income; // Employment Detail Person( std :: string name) : m_name(name) {} public : friend class PersonBuilder ; friend ostream& operator <<(ostream& os, const Person& obj); static PersonBuilder create ( std :: string name) ; };
Persona.cpp
# include <iostream> # include "Person.h" # include "PersonBuilder.h" PersonBuilder Person::create( string name) { return PersonBuilder{name}; } ostream& operator <<(ostream& os, const Person& obj) { return os << obj.m_name << std :: endl << "lives : " << std :: endl << "at " << obj.m_street_address << " with postcode " << obj.m_post_code << " in " << obj.m_city << std :: endl << "works : " << std :: endl << "with " << obj.m_company_name << " as a " << obj.m_position << " earning " << obj.m_annual_income; }
PersonBuilder.h
# pragma once # include "Person.h" class PersonBuilder { Person person; public : PersonBuilder( string name) : person(name) {} operator Person () const { return move(person); } PersonBuilder& lives () ; PersonBuilder& at ( std :: string street_address) ; PersonBuilder& with_postcode ( std :: string post_code) ; PersonBuilder& in ( std :: string city) ; PersonBuilder& works () ; PersonBuilder& with ( string company_name) ; PersonBuilder& as_a ( string position) ; PersonBuilder& earning ( string annual_income) ; };
PersonBuilder.cpp
# include "PersonBuilder.h" PersonBuilder& PersonBuilder::lives() { return * this ; } PersonBuilder& PersonBuilder::works() { return * this ; } PersonBuilder& PersonBuilder::with( string company_name) { person.m_company_name = company_name; return * this ; } PersonBuilder& PersonBuilder::as_a( string position) { person.m_position = position; return * this ; } PersonBuilder& PersonBuilder::earning( string annual_income) { person.m_annual_income = annual_income; return * this ; } PersonBuilder& PersonBuilder::at( std :: string street_address) { person.m_street_address = street_address; return * this ; } PersonBuilder& PersonBuilder::with_postcode( std :: string post_code) { person.m_post_code = post_code; return * this ; } PersonBuilder& PersonBuilder::in( std :: string city) { person.m_city = city; return * this ; }
Principal.cpp
# include <iostream> # include "Person.h" # include "PersonBuilder.h" using namespace std ; int main () { Person p = Person::create( "John" ) .lives() .at( "123 London Road" ) .with_postcode( "SW1 1GB" ) .in( "London" ) .works() .with( "PragmaSoft" ) .as_a( "Consultant" ) .earning( "10e6" ); cout << p << endl ; return EXIT_SUCCESS; }
¿Cuándo se debe utilizar el patrón de diseño del constructor?
Siempre que la creación de un nuevo objeto requiera configurar muchos parámetros y algunos de ellos (o todos ellos) son opcionales.
¿Por qué necesitamos una clase Builder cuando implementamos un patrón de diseño Builder?
No es necesario, pero hay algunos beneficios al hacerlo:
¡La mayor ventaja del patrón de diseño del constructor!
Código más expresivo.
MiClase o = new MiClase(5, 5.5, 'A', var, 1000, obj9, "hola");
¿Cuál es la diferencia entre Abstract Factory y Builder Design Pattern?
Publicado anteriormente en http://www.vishalchovatiya.com/builder-design-pattern-in-modern-cpp/