However, you must have a UML to make it clear. Generally, I only remember UML diagrams. Some patterns have their own fixed implementations.Code(Only part of this interface), especially in C #, the user is even treated as a client without exposing its internal implementation. Only encapsulated mode interfaces are published. So I will record some fixed implementation methods. There are also applicable scenarios (see more examples), advantages and disadvantages. Finally, the comparison between the horizontal view mode and the mode, the combination and the difference. All of the above have been done, and this kind of mental approach has become a positive result.
The idea of OO is also very important. The three basic features, especially peptides, interfaces and virtual classes, constructor and class, delegation, indexing, and generics, are worth exploring.
The following figure shows the UML diagram of the builder:
Builder: generator, abstract interface, and several virtual methods such as buildpart.
Concretebuilder: The getresult () method returns the generated product.
Director: the navigator that maintains a reference to the interface and can be instantiated by the client. This indirectly controls the buildpart () method in concretebuilder through the concrete () method (see below.
Public Void Concrete ()
{
B. buildpart ();//Here B comes from the builder parameter in Director constructor.
}
In this way, the director class implements interface-oriented programming, that isThe navigator director does not know what kind of concretebuilder is.Create interface "object" B and access its buildpart () virtual method.
So on the client side, I can write:
Concretebuilder B = New Concretebuilder ();
Director C = New Director (B ); // Add the generated class to the Navigator
C. Concrete ();
// Call B. getresult (); to return the generated object, that is, the product.
As you can see, if you want to use concretebuilderb instead of the original concretebuilder class, you only need to change the 1st sentence of the client
Concretebuilderb B = new concretebuilderb (); Do not change anything else. This is what the builder mode is pursuing.
Let's take a look at the example of "painting Facebook" to see how to use the builder mode. The Code is as follows:
Public Abstract Class Facebuilder
{
Public Abstract VoidBuildface ();
}
Public Class Guifacebuilder: facebuilder
{
Public Override Void Buildface ()
{
GRAP. drawellipse (p,100,100,200,300);
}
Private Graphics grap;
Private Pen P;
Public Guifacebuilder ()
{
GRAP=G;
P= NewPen (color. Red );
}
}
Public Class Facedirector
{
Private Facebuilder B;
Public Facedirector (facebuilder B)
{
This. B=B;
}
Public Void Createface ()
{
B. buildface ();
}
}
Note that the getresult method is not available in the sample generator. This is because G has been obtained and drawn, so the product is no longer returned and thus omitted.
Let's look back at the intention of the builder mode:
Separates the construction and representation of a complex object so that different representations can be created during the same building process. --Design Patterns
NOTE 1: The object construction process is encapsulated in ctor. The specific representation is completed by the concretebuilder. Thus the construction and representation are completely separated.
Note 2: The same ctor (build process ).
Note 3: For different concretebuilder expressions, the above concretebuilder object and concretebuilderb object have different types, that is, the builder mode does not care about the results.
Difference from Abstract Factory: Not long ago, I was asked to get stuck here. It was actually very simple. Abstract Factory generated a product series with the same interfaces. The finished products produced by builder mode can have different interfaces, as long as the creation process is the same method. In addition, for the abstract factory, the client does not need to know the specific type of the returned object, because the abstract factory constructs a product series with the same interface; For the builder mode, you must know the specific type of the returned object, because different generators return different types.
Another example is the logon interface, which supports both Windows applications and Web applications. This is a product interface with two different interfaces, but the UI is the same, so it must be implemented in the builder mode. You only need to ensure that different controls are thrown into the Panel during implementation of the virtual method, and the Panel object is returned through getresult. Use this panel on different clinet clients.
Note that the builder mode is builder + ctor, and the two are indispensable. the. NET platform has a stringbuilder, which is just a builder and has nothing to do with the mode.
In addition, in the. NET platform, pageClassOninit (). We are writingWebPage. HisCodebehindAll codes are inherited.System. Web. UI. PageBase class.Oninit ()Functions can be rewritten, which is also one of the applications in the builder mode: the navigator and builder interfaces are encapsulated in the framework. The generator is also encapsulated in the framework, but exposes a virtual method to implement oninit (), which is implemented by you. The client call mechanism is also automatically implemented during the page generation cycle. --. Net makes full use of the mode to facilitate developers, but it is not clear that developers generally do not pay attention to it.
Note:
1. Location of the getresult () method.
This article is about the specific generator. Can this method be put in the builder interface or omitted? The answer is yes.
1) if you do not need to return a product, you do not need to use the getresult method. For example, if you have implemented the G. Draw operation in the buildpart () method, it is not important to generate a product.
2) When a product needs to be returned, there are two situations: if these products have the same interface, you can abstract the getresult () method to the builder interface, because the same product type is returned. However, if the interfaces of these products are different, they must be implemented in specific generators.
2. disadvantages of builder: it is inconvenient to add a new builderpart () method. This is because, if you need to add a new builderpart (), you need to change the interface, the original generator, and the navigator at the same time. That is to say, it is impossible to change everything.
3. abstractfactory thinks that the construction process and production are very simple. At this time, if these products have the same interface, it is better to use abstract factory instead of builder.
4. Since Director and builder interfaces are inconvenient, can I add the concrete () method to the builder interface instead of director? At the same time, the buildpart () method of the builder interface is not exposed, and the access permission is set to protected (the specific generator can be rewritten ). The new UML diagram is as follows:
The code is: Public Abstract Class Builder
{
Protected Abstract Void Buildparta ();
Protected Abstract Void Buildpartb ();
Public Void Concrete ()
{
This. Buildparta ();
This. Buildpartb ();
}
}
Public Class Concretebuilder: Builder
{
Protected Override Void Buildparta ()
{
Console. writeline ();
}
Protected Override Void Buildpartb ()
{
Console. writeline ();
}
Public String Getresult ()
{
Return "1";
}
}
Public Class Client
{
Public Void Testbuilder ()
{
Concretebuilder Bui= NewConcretebuilder ();
Bui. Concrete ();
}
}
In this way, the regionalization becomes the template model, which does not reflect the purpose of builder. Especially when there are multiple navigators corresponding to a set of builder, it is necessary to abstract a ctor.