Статьи

Применен шаблон проектирования Builder

Всем привет!

Сегодня я расскажу о первой из совершенно новой серии шаблонов дизайна, которую я сделал. Шаблон конструктора является очень полезным и распространенным шаблоном при разработке серьезных приложений. В этой статье я расскажу о крошечной структуре шаблонов, так что вы всегда можете вернуться сюда и заставить ее работать.

Мнемоника, имея дело с шаблоном компоновщика, заключается в том, чтобы думать о настройке. Я всегда думаю об этом, когда выясняю, стоит ли мне его использовать или лучше взять завод. Вот так это работает лучше для меня. попробуй сам

UML

Вот как выглядит маленький каркас. Просто, красиво и понятно.

строитель

Код за этим

Код также очень простой, маленький, чистый и понятный. Мне нравится кодировать выразительно, поэтому мне не нужно много комментировать. В этом примере я сделал это, потому что он имеет учебный характер. Разрабатывая, я создал для себя какое-то соглашение. Я думаю, что это очень важно сделать. Это похоже на применение правильной грамматики на языке во время разработки.

Например: если я использую шаблон Builder, я всегда ставлю суффикс Builder в конце. Ну, вы можете сказать или подумать сейчас: что? Но это на самом деле очень, очень важная информация для начинающих и опытных разработчиков. Они автоматически увидят идею, стоящую за этим, и постараются не нарушать схему. На самом деле опытные разработчики полюбят это и попытаются продолжить хорошую работу, потому что они знают, что разработчик, который написал это, знает, что он сделал, и наверняка была причина для этого.

Поэтому всегда старайтесь быть достаточно ясным и давать правильную информацию о нужных местах. Кто-то еще поблагодарит вас позже. Но теперь к коду …

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
// 1. EXAMPLE: PARTS OF THE CUSTOMIZABLE PRODUCT WE WANT
public interface Part {
    // DEFINE THE METHODS YOUR PARTS WILL HAVE...
    void anyMethodNameYouLike();
}
 
// 2. THE BUILDER METHOD WILL ADD
// PARTS RETURNING THE BUILDER ITSELF
public interface BuildContract < B > {
    B mount(Part part);
}
 
// 3. DEFINE THE BUILDER'S CONTRUCTION METHOD
// WHICH BUILDS AND RETURNS THE FINAL PRODUCT "T"
public interface Builder < T > extends BuildContract < Builder < T > > {
    T build();
}

Реальный пример

Нет ничего лучше, чем это исправить и лучше понять. Давайте реализуем торт пекарню. Ваш коллега хочет открыть пекарню и попросил вас запрограммировать для него программное обеспечение пекарни. Давай сделаем это..!

И, между прочим, я от всей души рекомендую вам использовать инструмент диаграмм UML как механизм визуализации, чтобы показать ваши идеи и улучшить свои навыки проектирования. Начнем с UML:

builder_en

Аналогия

Давайте теперь воспользуемся нашим крошечным каркасом и проведем аналогию с нашей пекарней. Ингредиент — это часть, рецепт — это BuilderContract, а Builder — это сам строитель. Торт является конечным, настраиваемым продуктом. CakeBuilder — это класс, который на самом деле создает продукт после настройки (после добавления столько частей, сколько нужно ингредиентов). Клиент будет конечным клиентом или вашим коллегой, принимающим заказ. Просто используйте или воображение … Давайте сейчас погрузимся в код …

Ингредиенты (части)

Части в нашем примере являются ингредиентами. Давайте реализуем некоторые ингредиенты, чтобы использовать их позже, чтобы сделать торт.

1
2
3
4
5
6
7
// 1. EXAMPLE: PART TO CUSTOMIZATE "INGREDIENTS"
public interface Ingredient {
    // INGREDIENTS WILL HAVE...
    void printName();
    String getUnitPrice();
    void printCalories();
}
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
public class LightMilk implements Ingredient {
 
    private int deciLiter;
    private int calories;
    private String unitPrice;
     
    public LightMilk(int deciLiter){this.deciLiter=deciLiter;}
     
    public LightMilk(int deciLiter, int calories, String unitPrice) {
        super();
        this.deciLiter = deciLiter;
        this.calories = calories;
        this.unitPrice = unitPrice;
    }
 
    @Override public void printName() {System.out.printf(" Light Milk");}
    @Override public String getUnitPrice() {return unitPrice;}
    @Override public void printCalories() {System.out.printf(" 76kc");}
    public int getDeciLiter() {return deciLiter;}
    public void setDeciLiter(int deciLiter) {this.deciLiter = deciLiter;}
    public int getCalories() {return calories;}
    public void setCalories(int calories) {this.calories = calories;}
    public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;}
}
public class Sugar implements Ingredient {
 
    private int gram;
    private int calories;
    private String unitPrice;
     
    public Sugar(int deciLiter){this.gram=deciLiter;}
     
    public Sugar(int gram, int calories, String unitPrice) {
        super();
        this.gram = gram;
        this.calories = calories;
        this.unitPrice = unitPrice;
    }
 
    @Override public void printName() {System.out.printf(" Sugar");}
    @Override public String getUnitPrice() {return unitPrice;}
    @Override public void printCalories() {System.out.printf(" 40kc");}
    public int getGram() {return gram;}
    public void setGram(int gram) {this.gram = gram;}
    public int getCalories() {return calories;}
    public void setCalories(int calories) {this.calories = calories;}
    public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;}
}
public class Choco implements Ingredient {
    private int gram;
    private int calories;
    private String unitPrice;
    public Choco(int gram, int calories, String unitPrice) {
        super();
        this.gram = gram;
        this.calories = calories;
        this.unitPrice = unitPrice;
    }
    public int getGram() {return gram;}
    public void setGram(int gram) {this.gram = gram;}
    public int getCalories() {return calories;}
    public void setCalories(int calories) {this.calories = calories;}
    public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;}
 
    @Override public void printName() {System.out.printf(" Chocolate");}
    @Override public void printCalories() {System.out.printf(" 389kc");}
    @Override public String getUnitPrice() {return unitPrice;}
}
public class NoSugar implements Ingredient {
 
    private int gram;
    private int calories;
    private String unitPrice;
     
    public NoSugar(int deciLiter){this.gram=deciLiter;}
     
    public NoSugar(int gram, int calories, String unitPrice) {
        super();
        this.gram = gram;
        this.calories = calories;
        this.unitPrice = unitPrice;
    }
 
    @Override public void printName() {System.out.printf(" No Sugar");}
    @Override public String getUnitPrice() {return unitPrice;}
    @Override public void printCalories() {System.out.printf(" 0kc");}
    public int getGram() {return gram;}
    public void setGram(int gram) {this.gram = gram;}
    public int getCalories() {return calories;}
    public void setCalories(int calories) {this.calories = calories;}
    public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;}
}
public class Milk implements Ingredient {
 
    private int deciLiter;
    private int calories;
    private String unitPrice;
     
    public Milk(int deciLiter){this.deciLiter=deciLiter;}
     
    public Milk(int deciLiter, int calories, String unitPrice) {
        super();
        this.deciLiter = deciLiter;
        this.calories = calories;
        this.unitPrice = unitPrice;
    }
 
    @Override public void printName() {System.out.printf(" Milk");}
    @Override public String getUnitPrice() {return unitPrice;}
    @Override public void printCalories() {System.out.printf(" 128kc");}
    public int getDeciLiter() {return deciLiter;}
    public void setDeciLiter(int deciLiter) {this.deciLiter = deciLiter;}
    public int getCalories() {return calories;}
    public void setCalories(int calories) {this.calories = calories;}
    public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;}
}

Контракт строителя

Это рецепт в нашем примере.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 2. THE BUILDER METHOD WILL ADD
// INGREDIENTS RETURNING THE BUILDER ITSELF
public interface Recipe < B > {
    B addIngredient(Ingredient ingredient);
}
// 3. DEFINE THE BUILDER CONTRUCTION METHOD
// WHICH BUILDS AND RETURNS THE FINAL PRODUCT "T"
public interface Builder < T > extends Recipe < Builder < T > > {
    T build();
}
import java.util.ArrayList;
import java.util.List;
// 4. IMPLEMENT THE BUILDER ACC. TO YOUR NEEDS
public class CakeBuilder implements Builder < Cake > {
    // IN THIS CASE THE PARTS ARE THE INGREDIENTS
    private List < Ingredient > ingredients=new ArrayList < Ingredient > ( );
    @Override
    public Cake build() {
        if(!ingredients.isEmpty()){
            // THE FINAL PRODUCT IS A CHOCO-MUFFIN
            return new Cake(ingredients);
        }
        return new Cake(null);
    }
    @Override
    // BECAUSE I ALWAYS GET A BUILDER BACK, I'M ABLE TO
    // ADD A LOT OF PARTS BEFORE I CALL "BUILD()"
    public Builder < Cake > addIngredient(Ingredient ingredient) {
        if(ingredient!=null){
            ingredients.add(ingredient);
        }
        return this;
    }
}

Продукт

В нашем примере продукт для сборки — это торт.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.List;
 
public class Cake {
    public Cake(List < Ingredient > ingredients){
        String muffin = "";
        if(ingredients==null){
            System.out.println(" zero cake "+muffin);
            return;
        }
        // PRINT OUT MUFFIN INGREDIENTS
        System.out.printf(" Cake with: ");
        for (Ingredient ingredient : ingredients) {
            ingredient.printName();
        }
        // PRINT OUT PART PRICES
        for (Ingredient ingredient : ingredients) {
            muffin+=" "+ingredient.getUnitPrice();//NOPMD
        }
        System.out.println(" - Price: "+muffin);
    }
    public void printResult(){
        System.out.println(" Cake is ready!");
    }
}

Тестирование это

Наконец-то клиентский тест. Здесь мы можем увидеть использование этого:

01
02
03
04
05
06
07
08
09
10
11
// 5. TESTING THE CHOCO-BUILDER
public class Client {
    public static void main(String[] args) {
        Builder < Cake > chocoMuffinBuilder = new CakeBuilder();
        chocoMuffinBuilder.addIngredient(new Choco(10, 23, "3.39"));
        chocoMuffinBuilder.addIngredient(new Milk(34, 67, "1.57"));
        chocoMuffinBuilder.addIngredient(new Sugar(34, 67, "2.00"));
        final Cake chocoMuffin = chocoMuffinBuilder.build();
        chocoMuffin.printResult();
    }
}

Вот и все! Надеюсь, вам понравится!