Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package monster2;
- import java.util.Date;
- import mandatory.PersonCtors;
- import mandatory.PersonGotBuilderStaticCtors.Data;
- import mandatory.PersonGotBuilderStaticCtors.GotFirstName;
- import mandatory.PersonGotBuilderStaticCtors.GotHairColor;
- import mandatory.PersonGotBuilderStaticCtors.GotLastName;
- import mandatory.PersonGotBuilderStaticCtors.GotMiddleName;
- import mandatory.PersonGotBuilderStaticCtors.GotOptional;
- import mandatory.PersonGotBuilderStaticCtors.GotRequire;
- /**
- * Guides the adding of fields to make a person object. <br><br>
- *
- * Call doRequired() to start and doBuild() to finish
- */
- public class PersonBuilder {
- // -- Required -- //
- private String mFirstName;
- private String mMiddleName;
- private String mLastName;
- private String mNickName;
- private String mMaidenName;
- private String mEyeColor;
- private String mHairColor;
- private Date mDateOfBirth;
- private String[] mAliases;
- // -- Required Alternatives -- //
- //Not both; not neither
- private int mBeersToday; //One or
- private String mHowDrunk; //the other
- // .==== Using persons setters instead ====. //
- // -- Optional -- //
- //private String mClothing;
- //private String mTattoo;
- // -- Optional Alternatives -- //
- //Not both; either or neither
- //private String mFavoriteBeer; //Either
- //private String mJobTitle; //Or
- // '=======================================' //
- // -- What all the fuss is about -- //
- private Person mPerson;
- // -- Builder interface -- //
- /** Call each required method in order offered.*/
- public GotRequired doRequired() {
- return new GotRequired();
- }
- /*
- * Required constructor values
- *
- * Enforce initialization with type driven state machine
- *
- * Each Got... is a state. Each add... is a transition
- * Using a tree of states. Forking is fine but merging is not.
- * Tree allows the builds at the end of the paths to know each state visited.
- * Also allows states take the name of their one incoming transition.
- *
- * This creates a need to duplicate boiler plate code if forking happens early.
- * If a reordered presentation is acceptable put forking at the end
- * for simpler paths.
- *
- * Otherwise after the fork, where you might have merged, instead create
- * duplicate states. This will preserve memory of the fork and lead to the
- * proper constructor.
- *
- * Using this pattern any combination of constructors and setters should
- * be able to be supplied with values using this method.
- *
- */
- public class GotRequired {
- public GotFirstName addFirstName(String firstName) {
- mFirstName = firstName;
- return new GotFirstName();
- }
- }
- public class GotFirstName {
- public GotMiddleName addMiddleName(String middleName) {
- mMiddleName = middleName;
- return new GotMiddleName();
- }
- }
- public class GotMiddleName {
- public GotLastName addLastName(String lastName) {
- mLastName = lastName;
- return new GotLastName();
- }
- }
- public class GotLastName {
- public GotNickName addNickName(String nickName) {
- mNickName = nickName;
- return new GotNickName();
- }
- }
- public class GotNickName {
- public GotMaidenName addMaidenName(String maidenName) {
- mMaidenName = maidenName;
- return new GotMaidenName();
- }
- }
- public class GotMaidenName {
- public GotEyeColor addEyeColor(String eyeColor) {
- mEyeColor = eyeColor;
- return new GotEyeColor();
- }
- }
- public class GotEyeColor {
- public GotHairColor addHairColor(String hairColor) {
- mHairColor = hairColor;
- return new GotHairColor();
- }
- }
- public class GotHairColor {
- public GotDateOfBirth addDateOfBirth(Date dateOfBirth) {
- mDateOfBirth = dateOfBirth;
- return new GotDateOfBirth();
- }
- }
- public class GotDateOfBirth {
- public GotAliases addAliases(String... aliases) {
- mAliases = aliases;
- return new GotAliases();
- }
- }
- public class GotAliases {
- /** Controls alternatives that choose constructors */
- public GotRequiredAlternatives doRequiredAlternatives(){
- return new GotRequiredAlternatives();
- }
- }
- /*
- .addAlternatives() //Either x or y. a, b, or c. etc.
- .addBeersToday(3) //Now can't call addHowDrunk("Hammered");
- .addFavoriteBeer("Duff")//Now canβt call addJobTitle("Safety Inspector");
- .addBuild(); //Calls different constructors based on alternatives
- */
- /** Now the interesting forking bit */
- public class GotRequiredAlternatives {
- public GotPerson addBeersToday(int beersToday){
- mBeersToday = beersToday;
- //Got enough for constructor
- mPerson = new Person(
- mFirstName,
- mMiddleName,
- mLastName,
- mNickName,
- mMaidenName,
- mEyeColor,
- mHairColor,
- mDateOfBirth,
- mBeersToday, //GotBeersToday
- mAliases);
- return new GotPerson();
- }
- public GotPerson addHowDrunk(String howDrunk){
- mHowDrunk = howDrunk;
- //Got enough for constructor
- mPerson = new Person(
- mFirstName,
- mMiddleName,
- mLastName,
- mNickName,
- mMaidenName,
- mEyeColor,
- mHairColor,
- mDateOfBirth,
- mHowDrunk, //GotHowDrunk
- mAliases);
- return new GotPerson();
- }
- }
- //Could have created GotHowDrunk and GotBeersToday
- //but we're past the constructor choice so we can
- //forget the path that brought us here.
- public class GotPerson {
- /** Build Person object leaving optional fields set to default values */
- public Person doBuild() {
- return mPerson;
- }
- /** Call any or none of these optional fields */
- public GotOptional doOptional() {
- return new GotOptional();
- }
- }
- //Since person is not immutable the only thing gained here is confidence that these were set according to persons whacky rules
- class GotOptional {
- /** Build Person object */
- public Person doBuild() {
- return mPerson;
- }
- public GotOptionalAlternatives doOptionalAlternatives() {
- return new GotOptionalAlternatives();
- }
- public GotOptional addClothing(String clothing) {
- mPerson.setClothing(clothing);
- return this;
- }
- public GotOptional addTatoo(String tattoo) {
- mPerson.setTattoo(tattoo);
- return this;
- }
- //Add any number of setters that have good default values and do not conflict with each other
- }
- //Ideally person wouldn't allow this anyway but person is set in stone so at least this provides a safer interface
- public class GotOptionalAlternatives {
- /** Build Person object */
- public Person doBuild() {
- return mPerson;
- }
- //Optional but conflicting setters. Might never be called. Must never be called together.
- public GotFavoriteBeer addFavoriteBeer(String favoriteBeer){
- //mFavoriteBeer = favoriteBeer; //TODO remove
- mPerson.setFavoriteBeer(favoriteBeer); //GotFavoriteBeer
- return new GotFavoriteBeer();
- }
- public GotJobTitle addJobTitle(String jobTitle){
- //mJobTitle = jobTitle; //TODO remove
- mPerson.setJobTitle(jobTitle); //GotJobTitle
- return new GotJobTitle();
- }
- }
- //These are not strictly needed. They are like one-statement {}'s after an 'if'. Simply there if more gets added.
- public class GotFavoriteBeer {
- /** Build Person object */
- public Person doBuild() {
- return mPerson;
- }
- }
- public class GotJobTitle {
- /** Build Person object */
- public Person doBuild() {
- return mPerson;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement