Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

Panini

By: a guest on Nov 24th, 2012  |  syntax: Java  |  size: 9.53 KB  |  hits: 26  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.   This is only sort-of java. I've taken a few
  3.   liberties with the syntax for sugar's sake.
  4.  
  5.   Of note is the syntax for simple getters and setters:
  6.     The visibility of the getter is given by the
  7.       first visibility modifier. Then after the
  8.       identifier, the visibility of the setter
  9.       is given, then the behavior of the setter.
  10.       The setter takes as a parameter an object
  11.       of the same type as the field it sets, and
  12.       the name of that parameter is the same as
  13.       the name of the field it sets. The setter
  14.       shall return the value to assign to the
  15.       field. Nontrivial getters and more complex
  16.       setters must be built manually (their
  17.       advanced behavior is an important part of
  18.       their class's interface
  19.     If no inline setter behavior is defined, no
  20.       setter is automatically defined at all, and
  21.       it must be built manually.
  22.     If no inline setter behavior is defined, the
  23.       getter-visibility modifier is a normal
  24.       visibility modifier.
  25.     If an inline setter visibility is specified,
  26.       but no behavior is defined, it's assumed to
  27.       be a "trivial" setter, and the behavior (for
  28.       a field of name $name) is generated as
  29.       {return $name;}
  30.     If you want to specify package-visibility for
  31.       a setter, use the already-existing package
  32.       keyword
  33. */
  34. public class Main
  35. {
  36.   public static void main(String... args)
  37.   {
  38.     /* I don't know the names of any kinds of panini, or
  39.        the kinds of things that go them. */
  40.     /* A "classic" style construction: Lots of params, no names.
  41.        Even while writing this example, I forgot which order the
  42.        params were in, and had to check the implementation.
  43.        This method is very error-prone, because you could
  44.        accidentally set a panino with fish for bread.*/
  45.     Panino johns = new PaninoClassic("John", "Wheat", "Tuna",
  46.       "Provalone", "Salami", "Lettuce", "Tomato", "Another vegetable");
  47.     /* The classic Builder. It's a lot easier to call, and there's no
  48.        risk of setting bread="tuna", but it took some boilerplate
  49.        to implement the builder in the first place, and there's
  50.        no guarantee you got every field. Also, you can have a panini
  51.        with both meat and fish, which I assume violates business rules
  52.        because it doesn't seem to be possible in the StepBuilder.*/
  53.     Panino jerrys = new PaninoBuilder()
  54.         .paninoCalled("Jerry")
  55.         .setBreadType("Wheat")
  56.         .setFish("Tuna")
  57.         .setCheese("Provalone")
  58.         .setMeat("Salami")
  59.         .setVegetables("Vegetables")
  60.         .build();
  61.     /* The proposed stepbuilder. Safest of all, but absolutely horrific
  62.        to implement. Plus, the hinting only helps if you're working in
  63.        an IDE. I wrote this example from a POTE, and had to refer to the
  64.        (ginormous) PaninoStepBuilder implementation over and over again
  65.        to check I was doing everything in the right step. Also, it seems
  66.        you can't have a panini with meat and fish. Whoops. I'll also
  67.        take issue with his implementation of the panino class: If you're
  68.        not allowed to have both meat and fish, and they are both fillings,
  69.        you shouldn't give them each their own field, it should be
  70.        String filling, or fish and meat should have a distinct type*/
  71.     Panino jimmys = PaninoStepBuilder.newBuilder()
  72.         .paninoCalled("Jimmy")
  73.         .breadType("Wheat")
  74.         .fish("Tuna")
  75.         .withCheese("Provalone")
  76.         .addVegetable("tomato")
  77.         .addVegetable("lettuce")
  78.         .noMoreVegetablesPlease()
  79.         .build();
  80.     /* Finally, the classic constructor with named parameters. Easy to write,
  81.        easy to invoke. For very complicated classes with optional parameters,
  82.        default values, and other nontrivial business rules, you should
  83.        subclass.*/
  84.     Panino jeffs = new PaninoClassic(
  85.         name: "Jeff",
  86.         bread:"Wheat",
  87.         filling: "Tuna",
  88.         cheese: "Provalone",
  89.         vegetables: {"tomato","lettuce"});
  90.     /* Closing thoughts: The PaninoStepBuilder is more of a burden than a
  91.      * boon if you're not using an IDE. I was unable to exactly replicate
  92.      * the behavior of the StepBuilder with only named params, but that's
  93.      * mostly because the Panino class was flawed in its business logic. */
  94.   }
  95. }
  96. public class Panino
  97. {
  98.   private {
  99.     final String name public;
  100.     String breadType public;
  101.     String fish public;
  102.     String cheese public;
  103.     String meat public;
  104.     List<String> vegs public;
  105.   }
  106.   public Panino(String name)
  107.   {
  108.       this.name = name;
  109.   }
  110.  
  111.   @Override
  112.   public String toString()
  113.   {
  114.     return String.format("Panino [name=%s, breadType=%s,
  115.      fish=%s, cheese=%s, meat=%s, vegetables=%s]",
  116.       name, breadType, fish, cheese, meat, vegetables.toString());
  117.   }
  118. }
  119. /** A classic builder, as supplied. */
  120. public class PaninoBuilder
  121. {
  122.   private {
  123.     String name;
  124.     String breadType;
  125.     String fish;
  126.     String cheese;
  127.     String meat;
  128.     List vegetables = new ArrayList();
  129.   }
  130.   public PaninoBuilder paninoCalled(String name){
  131.     this.name = name;
  132.     return this;
  133.   }
  134.  
  135.   public PaninoBuilder breadType(String breadType){
  136.     this.breadType = breadType;
  137.     return this;
  138.   }
  139.  
  140.   public PaninoBuilder withFish(String fish){
  141.     this.fish = fish;
  142.     return this;
  143.   }
  144.  
  145.   public PaninoBuilder withCheese(String cheese){
  146.     this.cheese = cheese;
  147.     return this;
  148.   }
  149.  
  150.   public PaninoBuilder withMeat(String meat){
  151.     this.meat = meat;
  152.     return this;
  153.   }
  154.  
  155.   public PaninoBuilder withVegetable(String vegetable){  
  156.     vegetables.add(vegetable);
  157.     return this;
  158.   }
  159.   public Panino build()
  160.   {
  161.     Panino panino = new Panino(name);
  162.     panino.setBreadType(breadType);
  163.     panino.setCheese(cheese);
  164.     panino.setFish(fish);
  165.     panino.setMeat(meat);
  166.     panino.setVegetables(vegetables);
  167.     return panino;
  168.   }
  169. }
  170. /** The example step-builder as supplied. I haven't
  171.  * edited at all, because of how mad the amount of
  172.  * typing would be to implement it myself.
  173.  */
  174. public class PaninoStepBuilder
  175. {
  176.   public static FirstNameStep newBuilder()
  177.   {
  178.     return new Steps();
  179.   }
  180.   private PaninoStepBuilder() {}
  181.  
  182.   /**
  183.     * First Builder Step in charge of the Panino name.
  184.     * Next Step available : BreadTypeStep
  185.     */
  186.   public static interface FirstNameStep
  187.   {
  188.     BreadTypeStep paninoCalled(String name);
  189.   }
  190.  
  191.   /**
  192.     * This step is in charge of the BreadType.
  193.     * Next Step available : MainFillingStep
  194.     */
  195.   public static interface BreadTypeStep
  196.   {
  197.     MainFillingStep breadType(String breadType);
  198.   }
  199.  
  200.   /**
  201.     * This step is in charge of setting the main filling (meat or fish).
  202.     * Meat choice : Next Step available : CheeseStep
  203.     * Fish choice : Next Step available : VegetableStep
  204.     */
  205.   public static interface MainFillingStep
  206.   {
  207.     CheeseStep meat(String meat);
  208.     VegetableStep fish(String fish);
  209.   }
  210.  
  211.   /**
  212.     * This step is in charge of the cheese.
  213.     * Next Step available : VegetableStep
  214.     */
  215.   public static interface CheeseStep
  216.   {
  217.     VegetableStep noCheesePlease();
  218.     VegetableStep withCheese(String cheese);
  219.   }
  220.  
  221.   /**
  222.     * This step is in charge of vegetables.
  223.     * Next Step available : BuildStep
  224.     */
  225.   public static interface VegetableStep
  226.   {
  227.     BuildStep noMoreVegetablesPlease();
  228.     BuildStep noVegetablesPlease();
  229.     VegetableStep addVegetable(String vegetable);
  230.   }
  231.  
  232.   /**
  233.     * This is the final step in charge of building the Panino Object.
  234.     * Validation should be here.
  235.     */
  236.   public static interface BuildStep
  237.   {
  238.     Panino build();
  239.   }
  240.  
  241.   private static class Steps implements FirstNameStep, BreadTypeStep, MainFillingStep, CheeseStep, VegetableStep, BuildStep {
  242.  
  243.     private String name;
  244.     private String breadType;
  245.     private String meat;
  246.     private String fish;
  247.     private String cheese;
  248.     private final List<String> vegetables = new ArrayList<String>();
  249.  
  250.     public BreadTypeStep paninoCalled(String name)
  251.     {
  252.       this.name = name;
  253.       return this;
  254.     }
  255.  
  256.     public MainFillingStep breadType(String breadType)
  257.     {
  258.       this.breadType = breadType;
  259.       return this;
  260.     }
  261.  
  262.     public CheeseStep meat(String meat)
  263.     {
  264.       this.meat = meat;
  265.       return this;
  266.     }
  267.  
  268.     public VegetableStep fish(String fish)
  269.     {
  270.       this.fish = fish;
  271.       return this;
  272.     }
  273.  
  274.     public BuildStep noMoreVegetablesPlease()
  275.     {
  276.       return this;
  277.     }
  278.  
  279.     public BuildStep noVegetablesPlease()
  280.     {
  281.       return this;
  282.     }
  283.  
  284.  
  285.     public VegetableStep addVegetable(String vegetable)
  286.     {
  287.       this.vegetables.add(vegetable);
  288.       return this;
  289.     }
  290.  
  291.     public VegetableStep noCheesePlease()
  292.     {
  293.       return this;
  294.     }
  295.  
  296.     public VegetableStep withCheese(String cheese)
  297.     {
  298.       this.cheese = cheese;
  299.       return this;
  300.     }
  301.  
  302.     public Panino build()
  303.     {
  304.       Panino panino = new Panino(name);
  305.       panino.setBreadType(breadType);
  306.       if (fish != null) {
  307.               panino.setFish(fish);
  308.       } else {
  309.               panino.setMeat(meat);
  310.       }
  311.       if (cheese != null) {
  312.               panino.setCheese(cheese);
  313.       }
  314.       if (!vegetables.isEmpty()) {
  315.               panino.setVegetables(vegetables);
  316.       }
  317.       return panino;
  318.     }
  319.   }
  320. }
  321. public class PaninoClassic extends Panino
  322. {
  323.   public PaninoClassic(String name, String bread, String cheese,
  324.                        String filling, String... vegetables)
  325.   {
  326.     super(name);
  327.     setBreadType(bread);
  328.     setCheese(cheese);
  329.     setMeat(filling);
  330.     List<String> vegs = new ArrayList<>();
  331.     for(String s : vegetables) {
  332.       vegs.add(s);
  333.     }
  334.     setVegetables(vegs);
  335.   }
  336. }