When would you use the Builder Pattern? [closed]
Asked Answered
S

13

611

What are some common, real world examples of using the Builder Pattern? What does it buy you? Why not just use a Factory Pattern?

Slub answered 30/11, 2008 at 5:41 Comment(3)
Check out my InnerBuilder, an IntelliJ IDEA plugin that adds a 'Builder' action to the Generate menu (Alt+Insert) which generates an inner builder class as described in Effective Java github.com/analytically/innerbuilderLavina
The #35238792 mentioned some APIs that use builder patternEpigeal
Answers from Aaron and Tetha are really informative. Here is the full article related to those answers.Actually
U
285

The key difference between a builder and factory IMHO, is that a builder is useful when you need to do lots of things to build an object. For example imagine a DOM. You have to create plenty of nodes and attributes to get your final object. A factory is used when the factory can easily create the entire object within one method call.

One example of using a builder is a building an XML document, I've used this model when building HTML fragments for example I might have a Builder for building a specific type of table and it might have the following methods (parameters are not shown):

BuildOrderHeaderRow()
BuildLineItemSubHeaderRow()
BuildOrderRow()
BuildLineItemSubRow()

This builder would then spit out the HTML for me. This is much easier to read than walking through a large procedural method.

Check out Builder Pattern on Wikipedia.

Ukase answered 30/11, 2008 at 5:51 Comment(0)
G
1141

Below are some reasons arguing for the use of the pattern and example code in Java, but it is an implementation of the Builder Pattern covered by the Gang of Four in Design Patterns. The reasons you would use it in Java are also applicable to other programming languages as well.

As Joshua Bloch states in Effective Java, 2nd Edition:

The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters.

We've all at some point encountered a class with a list of constructors where each addition adds a new option parameter:

Pizza(int size) { ... }        
Pizza(int size, boolean cheese) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }

This is called the Telescoping Constructor Pattern. The problem with this pattern is that once constructors are 4 or 5 parameters long it becomes difficult to remember the required order of the parameters as well as what particular constructor you might want in a given situation.

One alternative you have to the Telescoping Constructor Pattern is the JavaBean Pattern where you call a constructor with the mandatory parameters and then call any optional setters after:

Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety.

The better alternative is to use the Builder Pattern.

public class Pizza {
  private int size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder {
    //required
    private final int size;

    //optional
    private boolean cheese = false;
    private boolean pepperoni = false;
    private boolean bacon = false;

    public Builder(int size) {
      this.size = size;
    }

    public Builder cheese(boolean value) {
      cheese = value;
      return this;
    }

    public Builder pepperoni(boolean value) {
      pepperoni = value;
      return this;
    }

    public Builder bacon(boolean value) {
      bacon = value;
      return this;
    }

    public Pizza build() {
      return new Pizza(this);
    }
  }

  private Pizza(Builder builder) {
    size = builder.size;
    cheese = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon = builder.bacon;
  }
}

Note that Pizza is immutable and that parameter values are all in a single location. Because the Builder's setter methods return the Builder object they are able to be chained.

Pizza pizza = new Pizza.Builder(12)
                       .cheese(true)
                       .pepperoni(true)
                       .bacon(true)
                       .build();

This results in code that is easy to write and very easy to read and understand. In this example, the build method could be modified to check parameters after they have been copied from the builder to the Pizza object and throw an IllegalStateException if an invalid parameter value has been supplied. This pattern is flexible and it is easy to add more parameters to it in the future. It is really only useful if you are going to have more than 4 or 5 parameters for a constructor. That said, it might be worthwhile in the first place if you suspect you may be adding more parameters in the future.

I have borrowed heavily on this topic from the book Effective Java, 2nd Edition by Joshua Bloch. To learn more about this pattern and other effective Java practices I highly recommend it.

Godber answered 23/12, 2009 at 15:52 Comment(36)
Different from the original GOF builder right? Because there is no Director Class. Seems almost like another pattern to me, but I agree it`s very useful.Thorma
For this particular example, wouldn't it be nicer to remove the boolean parameters and be able to say new Pizza.Builder(12).cheese().pepperoni().bacon().build();Toadeater
Sure - I just used the boolean values for the sake of example. In reality you would most likely be using a builder for more complex parameters.Godber
@Lino It actually is a form of the GOF Builder.Godber
@Lino Rosa, it is still a GOF builder pattern, the Pizza is the director. :-)Adhamh
This looks more like a Fluent Interface than a builder pattern.Chronological
@BuhakeSindi I suppose, but it's at the very least a simplified version of the GoF builder. For example, the GoF pattern as outlined in the book allows for the potential of building completely different products by simply replacing the builder within the client thereby reusing the director. It seems to me that in the Bloch Builder you'd have to duplicate the "director" in a new product.Payer
honestly, I find builder pattern more work for little gain compared to javabean patternGladisgladney
I still don't understand why you should use this. In the case above you could just use a class which contains the parameters you need to set (to gain the readability) and pass this parameter to a factory which will create the actual pizza.Tremann
@SACO, I can tell you the reason I use the pattern is to construct objects that do not have public setters. I can maintain better governance on my domain model this way. The builder is responsible for making sure I can only create valid variants of my domain object while methods on that object allow consumers to change its state. These methods can provide whatever guards are required and encapsulate all of the logic and state changes required to perform the required operation. If left to the consumer to set a new value for each property, etc. errors/violations will occur.Aneurysm
@Fabian Steeg, I think people are overreacting to to the nicer looking boolean setters, keep in mind that these kind of setters don't allow runtime changes: Pizza.Builder(12).cheese().pepperoni().bacon().build();, you would need to recompile your code or have unnecessary logic if you only need some pepperoni pizzas. At the very least you should also provide parametrized versions like @Kamikaze Mercenary originally suggested. Pizza.Builder(12).cheese(true).pepperoni(false).bacon(false).build();. Then again, we never unit-test, do we?Satisfactory
This implementation has neither Director nor ConcreteBuilder classes. It doesn't follow Builder pattern.Deontology
@JasonC Right, and what use is an immutable pizza anyway?Micron
@Gladisgladney you're assuming your builders will be for your own classes. What if you needed to wrap some other class? Do something based on the parameters like instantiate new objects for building? I have to agree that I would rather use the javabean pattern in my own work but both do have their place.Honoria
@Honoria in which case builder pattern is fine and worth it...Gladisgladney
@Gladisgladney I think the main problem is like with most programming questions. The answer oversimplifies the problem in order to help the OP understand. IMO, that is the main cause of the proverbial hammer.Honoria
The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors.Martella
@RobertHarvey How is this more like a fluent interface than a builder? This is a textbook builder class, and they're different things: https://mcmap.net/q/56173/-what-is-the-difference-between-a-fluent-interface-and-the-builder-patternRepetend
@doctordoder: You can have a builder that's not fluent. A fluent builder requires that the setter methods return this. You can also have fluent methods that are not builders; see Linq for an example.Chronological
@RobertHarvey Yeah, exactly. So I don't see why you say this is "more like" a fluent interface than a builder. Most builders are coded like this.Repetend
@doctordoder: My point is that the builder and the fluent interface are two different concepts. Yes, you can use them together, but the similarity pretty much ends there.Chronological
@insidesin: If only there were a way to write a constructor with optional arguments...Chronological
@Satisfactory You miss the point of the whole pattern when you write something like Pizza.Builder(12).cheese(true).pepperoni(false).bacon(false).build(); A key advantage of this pattern is, that you don't have to pass in default values for optional parameters, but can just leave them out completely, no matter the parameter order. So you could instead simply write Pizza.Builder(12).cheese(true).build(); However: Who in their right mind would order a pizza with just cheese and nothing else? ;-)Arsphenamine
@Arsphenamine I was specifically talking about runtime changes. Let's try an example for clarity: suppose a jsp page sends a list of ingredients (cheese tomato and basil). Your code would look like Pizza.Builder(12).cheese().tomato().basil().build(). Now, if you only like cheese your code would look like Pizza.Builder(12).cheese().build(); That would be a cumbersome way to build pizzas because you'd need to recompile your code for every order ;-)Satisfactory
@egallardo: So you are telling me that you do not rebuild your oven for every pizza that you bake? ;-) Yeah, in that case you are right, of course.Arsphenamine
You write "The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction" - could you please explain or give example to that inconsistent state? (except for when your program is multi-threaded)Centennial
in example presented by GOF there is a director class which takes Builders with common interface to create object representation while specific elements which are used to create this object are encapsulated. So the same process of construction can lead to diffrent object representations. These are adventages that example above doesn't provide. They only mention about class being director and product.Adulterant
the GOF builder pattern and the Bloch Builder pattern are completely different and non-related design patterns. This post is discussing the Bloch pattern and not the GOF one.Matherne
@Godber I havea doubt, as you said setter approach will leade to "The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction". But same could be said about Builder pattern, if we forget to call the builder's data access method for eg. if we forget to call .pepperoni(true) the object will be in inconsistent state.Idea
@Godber Someone copy and pasted your answer as a blog post medium.com/@modestofiguereo/…Grandsire
@Aaron: In order to rely on an immutable object and/or an object that is properly constructed and valid according to your business rules you should declare class Pizza final. Otherwise someone could subclass Pizza and create an instance of it which is mutable and has invalid state.Ilanailangilang
"The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction." i did not understand how this problem is solved in the example. If i skip pizza.setCheese(true); call in the JavaBean pattern, I can skip it Pizza pizza = new Pizza.Builder(12).build(); in the builder pattern too and will get the same inconsistent behavior. Am i missing something?Befit
@Godber I am confused about "The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety." If one thread is creating one object in one method stack then how thread safety becomes a concern here?Elisabethelisabethville
@BarışAkkurt yes you are. After you .build() your pizza you can no longer change it, you can recreate it from scratch but that's it. Until you fully built your object you cannot use it and that's the point, with setters you can start using partly created-inconsistent object immediately, now imagine calling all setters of single class in 20 other different classes - good luck, with builder you can't. My team is also obsessed with builders trying to achieve immutability through this everywhere, I can only say that Kotlin with default parameters + val's is to the rescue.Cornetist
Why not use these patterns over builder: makePizza $ {size: 12, toppings: [Pepperoni, Cheese, Bacon]}, makePizza({size: 12, fields: ['pepperoni', 'cheese', 'bacon']}), (make-pizza :size 12 :fields '(pepperoni cheese 'bacon))Nairobi
to actually answer the question "what are some real world examples" instead of discussing what builder pattern is; it would be things like: email template builder with attachments, report builder, constructing URL strings, route builder, query builder, middleware pattern. we would use builder pattern in any scenario where creating objects is expensive. ie. the data held by the object might be queried from a database, or requested through http, or calculated with a long running CPU process, or from dependencies. in any such 'lazy' initializations of objects builder pattern would be helpfulSquire
S
350

Consider a restaurant. The creation of "today's meal" is a factory pattern, because you tell the kitchen "get me today's meal" and the kitchen (factory) decides what object to generate, based on hidden criteria.

The builder appears if you order a custom pizza. In this case, the waiter tells the chef (builder) "I need a pizza; add cheese, onions and bacon to it!" Thus, the builder exposes the attributes the generated object should have, but hides how to set them.

Sauropod answered 30/11, 2008 at 19:0 Comment(1)
Nitin extended the kitchen analogy in another answer to this question.Ouse
U
285

The key difference between a builder and factory IMHO, is that a builder is useful when you need to do lots of things to build an object. For example imagine a DOM. You have to create plenty of nodes and attributes to get your final object. A factory is used when the factory can easily create the entire object within one method call.

One example of using a builder is a building an XML document, I've used this model when building HTML fragments for example I might have a Builder for building a specific type of table and it might have the following methods (parameters are not shown):

BuildOrderHeaderRow()
BuildLineItemSubHeaderRow()
BuildOrderRow()
BuildLineItemSubRow()

This builder would then spit out the HTML for me. This is much easier to read than walking through a large procedural method.

Check out Builder Pattern on Wikipedia.

Ukase answered 30/11, 2008 at 5:51 Comment(0)
C
20

.NET StringBuilder class is a great example of builder pattern. It is mostly used to create a string in a series of steps. The final result you get on doing ToString() is always a string but the creation of that string varies according to what functions in the StringBuilder class were used. To sum up, the basic idea is to build complex objects and hide the implementation details of how it is being built.

Catchy answered 20/3, 2009 at 1:46 Comment(5)
I don't think that that's the builder pattern. The StringBuilder is just another implementation of a character array class (i.e. string), but it makes performance and memory management into account, because strings are immutable.Slub
It is absolutely the builder pattern, as is the StringBuilder class in Java. Notice how the append() method of both of these classes returns StringBuilder itself, so that one can chain b.append(...).append(...) before finally calling toString(). Citation: infoq.com/articles/internal-dsls-javaAugustinaaugustine
@Augustinaaugustine Ya I don't think that's really a builder pattern, I'd say that's more just a fluent interface.Phenomenon
"Notice how the append() method of both of these classes returns StringBuilder itself" thats not the Builder pattern, thats just a fluent interface. Its just that often a Builder will ALSO use a fluent interface. A Builder doesnt have to have a fluent interface.Caress
But note that StringBuilder by nature is not synchronized, unlike the StringBuffer which is synchronized.Gyp
B
17

I always disliked the Builder pattern as something unwieldy, obtrusive and very often abused by less experienced programmers. Its a pattern which only makes sense if you need to assemble the object from some data which requires a post-initialisation step (i.e. once all the data is collected - do something with it). Instead, in 99% of the time builders are simply used to initialise the class members.

In such cases it is far better to simply declare withXyz(...) type setters inside the class and make them return a reference to itself.

Consider this:

public class Complex {

    private String first;
    private String second;
    private String third;

    public String getFirst(){
       return first; 
    }

    public void setFirst(String first){
       this.first=first; 
    }

    ... 

    public Complex withFirst(String first){
       this.first=first;
       return this; 
    }

    public Complex withSecond(String second){
       this.second=second;
       return this; 
    }

    public Complex withThird(String third){
       this.third=third;
       return this; 
    }

}


Complex complex = new Complex()
     .withFirst("first value")
     .withSecond("second value")
     .withThird("third value");

Now we have a neat single class that manages its own initialization and does pretty much the same job as the builder, except that its far more elegant.

Bearded answered 7/10, 2014 at 13:16 Comment(3)
I just decided I wanted to build my complex XML document as JSON. Firstly, how do I know that class 'Complex' is capable of delivering an XMLable product in the first place and how would I change it to produce a JSONable object? Quick answer: I can't because I need to use builders. And we come full circle...Annulus
total bs , Builder is designed to build immutable objects and with ability change the way of building in future without touching the product classConeflower
hmmm? Did you read somewhere in the answer me saying what Builder is designed for? It is an alternative point of view to the question at the top "When would you use the Builder Pattern?", which is based on experience of countless abuse of the pattern, where something much simpler does the job better. All patterns are useful if you know when and how to use them - that's the whole point of documenting the patterns in the first place! When pattern is overused or worse - misused - then is becomes an anti-pattern within the context of your code. Alas...Bearded
J
12

For a multi-threaded problem, we needed a complex object to be built up for each thread. The object represented the data being processed, and could change depending on the user input.

Could we use a factory instead? Yes

Why didn't we? Builder makes more sense I guess.

Factories are used for creating different types of objects that are the same basic type (implement the same interface or base class).

Builders build the same type of object over and over, but the construction is dynamic so it can be changed at runtime.

Juliannjulianna answered 30/11, 2008 at 5:51 Comment(0)
S
10

You use it when you have lots of options to deal with. Think about things like jmock:

m.expects(once())
    .method("testMethod")
    .with(eq(1), eq(2))
    .returns("someResponse");

It feels a lot more natural and is...possible.

There's also xml building, string building and many other things. Imagine if java.util.Map had put as a builder. You could do stuff like this:

Map<String, Integer> m = new HashMap<String, Integer>()
    .put("a", 1)
    .put("b", 2)
    .put("c", 3);
Smelly answered 30/11, 2008 at 5:50 Comment(4)
I forgot to read the "if" map implemented a builder pattern and was suprised to see the construct there.. :)Kierakieran
:) Sorry about that. It's common in many languages to return self instead of void. You can do it in java, but it's not very common.Smelly
The map example is simply an example of method chaining.Yggdrasil
@Yggdrasil It would actually be closer to method cascading. Though it's using chaining in a way that simulates cascading, so it's obviously is chaining, but semantically it behaves as cascading.Phenomenon
B
10

While going through Microsoft MVC framework, I got a thought about builder pattern. I came across the pattern in the ControllerBuilder class. This class is to return the controller factory class, which is then used to build concrete controller.

Advantage I see in using builder pattern is that, you can create a factory of your own and plug it into the framework.

@Tetha, there can be a restaurant (Framework) run by Italian guy, that serves Pizza. In order to prepare pizza Italian guy (Object Builder) uses Owen (Factory) with a pizza base (base class).

Now Indian guy takes over the restaurant from Italian guy. Indian restaurant (Framework) servers dosa instead of pizza. In order to prepare dosa Indian guy (object builder) uses Frying Pan (Factory) with a Maida (base class)

If you look at scenario, food is different,way food is prepared is different, but in the same restaurant (under same framework). Restaurant should be build in such a way that it can support Chinese, Mexican or any cuisine. Object builder inside framework facilitates to plugin kind of cuisine you want. for example

class RestaurantObjectBuilder
{
   IFactory _factory = new DefaultFoodFactory();

   //This can be used when you want to plugin the 
   public void SetFoodFactory(IFactory customFactory)
   {
        _factory = customFactory;
   }

   public IFactory GetFoodFactory()
   {
      return _factory;
   }
}
Bodyguard answered 17/11, 2010 at 6:45 Comment(0)
C
8

Building on the previous answers (pun intended), an excellent real-world example is Groovy's built in support for Builders.

See Builders in the Groovy Documentation

Cuomo answered 30/11, 2008 at 17:51 Comment(0)
T
7

Another advantage of the builder is that if you have a Factory, there is still some coupling in you code, because for the Factory to work, it has to know all the objects it can possibly create. If you add another object that could be created, you will have to modify the factory class to include him. This happens in the Abstract Factory as well.

With the builder, on the other hand, you just have to create a new concrete builder for this new class. The director class will stay the same, because it receives the builder in the constructor.

Also, there are many flavors of builder. Kamikaze Mercenary`s gives another one.

Thorma answered 24/12, 2009 at 0:20 Comment(0)
D
5
/// <summary>
/// Builder
/// </summary>
public interface IWebRequestBuilder
{
    IWebRequestBuilder BuildHost(string host);

    IWebRequestBuilder BuildPort(int port);

    IWebRequestBuilder BuildPath(string path);

    IWebRequestBuilder BuildQuery(string query);

    IWebRequestBuilder BuildScheme(string scheme);

    IWebRequestBuilder BuildTimeout(int timeout);

    WebRequest Build();
}

/// <summary>
/// ConcreteBuilder #1
/// </summary>
public class HttpWebRequestBuilder : IWebRequestBuilder
{
    private string _host;

    private string _path = string.Empty;

    private string _query = string.Empty;

    private string _scheme = "http";

    private int _port = 80;

    private int _timeout = -1;

    public IWebRequestBuilder BuildHost(string host)
    {
        _host = host;
        return this;
    }

    public IWebRequestBuilder BuildPort(int port)
    {
        _port = port;
        return this;
    }

    public IWebRequestBuilder BuildPath(string path)
    {
        _path = path;
        return this;
    }

    public IWebRequestBuilder BuildQuery(string query)
    {
        _query = query;
        return this;
    }

    public IWebRequestBuilder BuildScheme(string scheme)
    {
        _scheme = scheme;
        return this;
    }

    public IWebRequestBuilder BuildTimeout(int timeout)
    {
        _timeout = timeout;
        return this;
    }

    protected virtual void BeforeBuild(HttpWebRequest httpWebRequest) {
    }

    public WebRequest Build()
    {
        var uri = _scheme + "://" + _host + ":" + _port + "/" + _path + "?" + _query;

        var httpWebRequest = WebRequest.CreateHttp(uri);

        httpWebRequest.Timeout = _timeout;

        BeforeBuild(httpWebRequest);

        return httpWebRequest;
    }
}

/// <summary>
/// ConcreteBuilder #2
/// </summary>
public class ProxyHttpWebRequestBuilder : HttpWebRequestBuilder
{
    private string _proxy = null;

    public ProxyHttpWebRequestBuilder(string proxy)
    {
        _proxy = proxy;
    }

    protected override void BeforeBuild(HttpWebRequest httpWebRequest)
    {
        httpWebRequest.Proxy = new WebProxy(_proxy);
    }
}

/// <summary>
/// Director
/// </summary>
public class SearchRequest
{

    private IWebRequestBuilder _requestBuilder;

    public SearchRequest(IWebRequestBuilder requestBuilder)
    {
        _requestBuilder = requestBuilder;
    }

    public WebRequest Construct(string searchQuery)
    {
        return _requestBuilder
        .BuildHost("ajax.googleapis.com")
        .BuildPort(80)
        .BuildPath("ajax/services/search/web")
        .BuildQuery("v=1.0&q=" + HttpUtility.UrlEncode(searchQuery))
        .BuildScheme("http")
        .BuildTimeout(-1)
        .Build();
    }

    public string GetResults(string searchQuery) {
        var request = Construct(searchQuery);
        var resp = request.GetResponse();

        using (StreamReader stream = new StreamReader(resp.GetResponseStream()))
        {
            return stream.ReadToEnd();
        }
    }
}

class Program
{
    /// <summary>
    /// Inside both requests the same SearchRequest.Construct(string) method is used.
    /// But finally different HttpWebRequest objects are built.
    /// </summary>
    static void Main(string[] args)
    {
        var request1 = new SearchRequest(new HttpWebRequestBuilder());
        var results1 = request1.GetResults("IBM");
        Console.WriteLine(results1);

        var request2 = new SearchRequest(new ProxyHttpWebRequestBuilder("localhost:80"));
        var results2 = request2.GetResults("IBM");
        Console.WriteLine(results2);
    }
}
Deontology answered 16/1, 2014 at 12:55 Comment(2)
You can improve your answers two ways: 1) Make it SSCCE. 2) Explain how this answers the question.Ninetta
Instead of using the builder pattern can't you use JSON or s-expression based eDSLs? (search-request :host "ajax.googleapis.com" :port 80 :path "ajax/services/search/web" :query (string "v=1.0&q=" (HttpUtility.UrlEncode searchQuery)))Nairobi
T
3

I used builder in home-grown messaging library. The library core was receiving data from the wire, collecting it with Builder instance, then, once Builder decided it've got everything it needed to create a Message instance, Builder.GetMessage() was constructing a message instance using the data collected from the wire.

Talkative answered 30/11, 2008 at 18:5 Comment(0)
S
3

When I wanted to use the standard XMLGregorianCalendar for my XML to object marshalling of DateTime in Java, I heard a lot of comments on how heavy weight and cumbersome it was to use it. I was trying to comtrol the XML fields in the xs:datetime structs to manage timezone, milliseconds, etc.

So I designed a utility to build an XMLGregorian calendar from a GregorianCalendar or java.util.Date.

Because of where I work I'm not allowed to share it online without legal, but here's an example of how a client uses it. It abstracts the details and filters some of the implementation of XMLGregorianCalendar that are less used for xs:datetime.

XMLGregorianCalendarBuilder builder = XMLGregorianCalendarBuilder.newInstance(jdkDate);
XMLGregorianCalendar xmlCalendar = builder.excludeMillis().excludeOffset().build();

Granted this pattern is more of a filter as it sets fields in the xmlCalendar as undefined so they are excluded, it still "builds" it. I've easily added other options to the builder to create an xs:date, and xs:time struct and also to manipulate timezone offsets when needed.

If you've ever seen code that creates and uses XMLGregorianCalendar, you would see how this made it much easier to manipulate.

Stevenstevena answered 18/3, 2011 at 14:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.