Builder pattern
introduce
Builder Pattern uses multiple simple objects to build a complex object step by step
Definition: Separate the construction of a complex object from its
representation sothat the same construction process can create
different representations. (separate the construction of a complex object from its representation, so that the same construction process can create different representations.)
Main solutions: it mainly solves the problem of creating "a complex object" in software system, which is usually composed of sub objects of each part with certain algorithms; Due to the change of requirements, each part of this complex object often faces drastic changes, but the algorithm that combines them is relatively stable.
When to use: when some basic components will not change, but their combinations often change.
How to solve: separate change from invariance.
Key codes:
Builder: create and provide instances,
Director: manage the dependencies of built instances.
Class diagram:
Product: product class, which usually implements the template method pattern, that is, there are template methods and basic methods
Builder: Abstract Builder (abstract class or interface), which specifies the components of the product. It is generally implemented by subclasses
ConcreteBuilder: the concrete builder implements all the methods defined by the abstract builder and returns a component object
Director: Director class, which is responsible for arranging the order of existing modules, and then telling Builder to start construction
Code implementation:
If we want to assemble a batch of iPhone s and OPPO phones:
If the assembly process is mainly divided into two parts: assembly and appearance design
The steps of these two mobile phones are different
iPhone: assembly and appearance design (brand logo printing and appearance coloring)
OPPO: assembly and appearance design (appearance coloring and brand logo printing)
C++
class PhoneBuilder{ public: virtual void Package() = 0; virtual void Design() = 0; std::string GetResult(){ return _phone; } protected: void Logo() ; void Color() ; protected: std::string _phone; }; class iPhone :public PhoneBuilder{ public: void Package(){ _phone += "packing\n"; } void Design(){ Logo(); Color(); } std::string GetResult(){ return _phone; } protected: void Logo(){ _phone += "Logo iPhone\n"; } void Color(){ _phone += "Set Red color\n"; } }; class OPPO :public PhoneBuilder{ public: void Package(){ _phone += "Packing\n"; } void Design(){ Color(); Logo(); } std::string GetResult(){ return _phone; } protected: void Logo(){ _phone += "Logo OPPO\n"; } void Color(){ _phone += "Set white color\n"; } }; class PhoneDirector{ public: void Package(PhoneBuilder* o){ o->Package(); o->Design(); } };
test
PhoneDirector pd; PhoneBuilder* o=new OPPO; pd.Package(o); std::cout << o->GetResult() << std::endl; PhoneBuilder* i = new iPhone; pd.Package(i); std::cout << i->GetResult() << std::endl;
go
package Builder type PhoneBuilder interface{ Package() Design() GetResult()string } type phone struct{ _phone string } func (p *phone)GetResult()string{ return p._phone } type IPhone struct{ phone } func (p *IPhone)Package(){ p._phone +="Packaging iPhone\n" } func (p *IPhone)Design(){ p.logo() p.color() } func (p *IPhone)logo(){ p._phone +="Logo iPhone\n" } func (p *IPhone)color(){ p._phone += "Set red color\n" } type OPPO struct{ phone } func (p *OPPO)Package(){ p._phone +="Packaging OPPO\n" } func (p *OPPO)Design(){ p.logo() p.color() } func (p *OPPO)logo(){ p._phone +="Logo OPPO\n" } func (p *OPPO)color(){ p._phone += "Set white color\n" } type PhoneDirectorInterface interface{ Produce(pb PhoneBuilder) } type PhoneDirectorStruct struct{ } func (p *PhoneDirectorStruct)Produce(pb PhoneBuilder){ pb.Package() pb.Design() }
test
package main import ( "fmt" b "Builder" ) func main(){ pd :=b.PhoneDirectorStruct{} fmt.Println("Produce iPhone") iphone :=&b.IPhone{} pd.Produce(iphone) fmt.Println(iphone.GetResult()) fmt.Println("Produce OPPO") oppo :=&b.OPPO{} pd.Produce(oppo) fmt.Println(oppo.GetResult()) }
Advantages and disadvantages
advantage:
1. The builder is independent and easy to expand.
2. Easy to control detail risk.
Since the specific builders are independent, the construction process will be gradually refined without any impact on other modules
Disadvantages:
1. Products must have common ground and limited scope.
2. If the internal changes are complex, there will be many construction classes.
Usage scenario
1. The object to be generated has a complex internal structure.
2. The internal properties of the object to be generated depend on each other.
Difference from factory mode
matters needing attention:
The difference from the factory mode is that the builder mode pays more attention to the assembly sequence of parts.