官术网_书友最值得收藏!

Builder

In our fictional world, we sometimes have some rather complicated classes that need to be constructed. The classes contain different implementations of an interface depending on how they are constructed. In order to simplify the building of these classes and encapsulate the knowledge of building the class away from the consumers, a builder may be used. Multiple concrete builders reduce the complexity of the constructor in the implementation. When new builders are required, a constructor does not need to be added, a new builder just needs to be plugged in.

Tournaments are an example of a complicated class. Each tournament has a complicated setup involving the events, the attendees, and the prizes. Much of the setup for these tournaments is similar: each one has a joust, archery, and a melee. Creating a tournament from multiple places in the code means that the responsibility of knowing how to construct a tournament is distributed. If there is a need to change the initiation code, then it must be done in a lot of different places.

Employing a Builder pattern avoids this issue by centralizing the logic necessary to build the object. Different concrete builders can be plugged into the builder to construct different complicated objects, as shown in the following diagram:

Implementation

Let's drop in and look at some of the code. To start with, we'll create a number of utility classes, which will represent the parts of a tournament. We can see this in the following code:

var Event = (function () {
  function Event(name) {
    this.name = name;
  }
  return Event;
})();
Westeros.Event = Event;

var Prize = (function () {
  function Prize(name) {
    this.name = name;
  }
  return Prize;
})();
Westeros.Prize = Prize;

var Attendee = (function () {
  function Attendee(name) {
    this.name = name;
  }
  return Attendee;
})();
Westeros.Attendee = Attendee;

The tournament itself is a very simple class as we don't need to assign any of the public properties explicitly, as shown in the following code:

var Tournament = (function () {
  this.Events = [];
  function Tournament() {
  }
  return Tournament;
})();
Westeros.Tournament = Tournament;

We'll implement two builders that create different tournaments. This can be seen in the following code:

var LannisterTournamentBuilder     = (function () {
  function LannisterTournamentBuilder() {
  }
  LannisterTournamentBuilder.prototype.build = function () {
    var tournament = new Tournament();
    tournament.events.push(new Event("Joust"));
    tournament.events.push(new Event("Melee"));

    tournament.attendees.push(new Attendee("Jamie"));

    tournament.prizes.push(new Prize("Gold"));
    tournament.prizes.push(new Prize("More Gold"));

    return tournament;
  };
  return LannisterTournamentBuilder;
})();
Westeros.LannisterTournamentBuilder = LannisterTournamentBuilder;

var BaratheonTournamentBuilder = (function () {
  function BaratheonTournamentBuilder() {
  }
  BaratheonTournamentBuilder.prototype.build = function () {
    var tournament = new Tournament();
    tournament.events.push(new Event("Joust"));
    tournament.events.push(new Event("Melee"));

    tournament.attendees.push(new Attendee("Stannis"));
    tournament.attendees.push(new Attendee("Robert"));

    return tournament;
  };
  return BaratheonTournamentBuilder;
})();
Westeros.BaratheonTournamentBuilder = BaratheonTournamentBuilder;

Finally, the director, or as we're calling it TournamentBuilder, simply takes a builder and executes it:

var TournamentBuilder = (function () {
  function TournamentBuilder() {
  }
  TournamentBuilder.prototype.build = function (builder) {
    return builder.build();
  };
  return TournamentBuilder;
})();
Westeros.TournamentBuilder = TournamentBuilder;

Again, you'll see that the JavaScript implementation is far simpler than the traditional implementation as there is no need for interfaces.

Builders need not return a fully realized object. This means that you can create a builder that partially hydrates an object, then allows the object to be passed onto another builder for it to finish. This approach allows us to divide the work of building an object amongst several classes with limited responsibility. In our preceding example, we could have a builder that is responsible for populating the events and another that is responsible for populating the attendees.

Does the builder pattern still make sense in view of JavaScript's prototype extension model? I believe so. There are still cases where a complicated object needs to be created according to different approaches.

主站蜘蛛池模板: 修武县| 保亭| 清远市| 西峡县| 乌什县| 墨玉县| 榆树市| 德庆县| 商丘市| 宾阳县| 武山县| 虹口区| 上饶县| 开封县| 新邵县| 郁南县| 定陶县| 榆社县| 浦北县| 曲阜市| 武川县| 沙湾县| 怀化市| 于田县| 南和县| 密山市| 桐柏县| 亚东县| 万荣县| 方山县| 老河口市| 盘锦市| 丽江市| 罗山县| 遂昌县| 河西区| 曲靖市| 冀州市| 班戈县| 万安县| 黄陵县|