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

2.5 應用建造者模式

建造者設計模式是最有用的創建型模式之一,因為它將較小的對象構建成較大的對象。這正是我們想要做的——從原料列表中構建出一個三明治對象。建造者模式還有一個更大的優勢,就是以后可以很容易地增加可選功能。和以前一樣,先要創建一個稱為Ingredient的接口,并用它來表示Bread和Filling。這一次需要將熱值表示為整數類型,因為我們需要計算成品三明治的總熱量。

打開一個Android Studio項目或啟動一個新項目,然后按照以下步驟創建一個基本的三明治建造者模式。

(1)創建一個名為Ingredient.java的新接口,用如下代碼實現:

    public interface Ingredient {
        String name();
        int calories();
    }

(2)創建一個名為Bread的抽象類:

    public abstract class Bread implements Ingredient {
        @Override
        public abstract String name();
        @Override
        public abstract int calories();
    }

(3)創建一個一樣的抽象類——Filling。

    (4)接下來,創建Bread的具體類:
    public class Bagel extends Bread {
        @Override
        public String name() {
            return "Bagel";
        }
        @Override
        public int calories() {
            return 250;
        }
    }

(5)對Filling類進行相同的操作。每種類型定義兩個類,已經足夠達到演示的目的:

    public class SmokedSalmon extends Filling {
        @Override
        public String name() {
            return "Smoked salmon";
        }
        @Override
        public int calories() {
            return 400;
        }
    }

(6)現在可以創建Sandwich類:

    public class Sandwich {
        private static final String DEBUG_TAG = "tag";
        //創建持有原料的列表
        private List<Ingredient> ingredients = new ArrayList<Ingredient>();
        //計算總熱值
        public void getCalories() {
            int c = 0;
            for (Ingredient i : ingredients) {
                c+= i.calories();
            }
            Log.d(DEBUG_TAG, "Total calories : "+c+" kcal");
        }
        //添加原料
        public void addIngredient(Ingredient ingredient) {
            ingredients.add(ingredient);
        }
        //輸出原料
        public void getSandwich() {
            for (Ingredient i : ingredients) {
                Log.d(DEBUG_TAG, i.name()+" : "+i.calories()+" kcal");
            }
        }
    }

(7)最后,創建SandwichBuilder類:

    public class SandwichBuilder {
        //現成的三明治
        public static Sandwich readyMade() {
            Sandwich sandwich = new Sandwich();
              sandwich.addIngredient(new Bagel());
              sandwich.addIngredient(new SmokedSalmon());
              sandwich.addIngredient(new CreamCheese());
              return sandwich;
            }
            //定制三明治
            public static Sandwich build(Sandwich s, Ingredient i) {
              s.addIngredient(i);
              return s;
            }
        }

建造者設計模式已經完成,至少目前如此,如圖2-12所示。

圖2-12

這里,我們為建造者提供了兩個功能:返回現成的三明治和用戶定制的三明治。現在還沒有可使用的界面,但是我們可以通過客戶端代碼模擬用戶的選擇。

我們還將輸出的職責委托給了Sandwich類,這通常是一個明智的選擇,因為這有助于保持客戶端代碼整潔和清晰,正如下邊的代碼所示:

        //創建一個定制的三明治
        SandwichBuilder builder = new SandwichBuilder();
        Sandwich custom = new Sandwich();
        //模擬用戶的選擇
        custom = builder.build(custom, new Bun());
        custom = builder.build(custom, new CreamCheese());
        Log.d(DEBUG_TAG, "CUSTOMIZED");
        custom.getSandwich();
        custom.getCalories();
        //創建一個現成的三明治
        Sandwich offTheShelf = SandwichBuilder.readyMade();
        Log.d(DEBUG_TAG, "READY MADE");
        offTheShelf.getSandwich();
        offTheShelf.getCalories();

代碼將產生如下輸出:

    D/tag: CUSTOMIZED
    D/tag: Bun : 150 kcal
    D/tag: Cream cheese : 350 kcal
    D/tag: Total calories : 500 kcal
    D/tag: READY MADE
    D/tag: Bagel : 250 kcal
    D/tag: Smoked salmon : 400 kcal
    D/tag: Cream cheese : 350 kcal
    D/tag: Total calories : 1000 kcal

建造者最大的優點之一是非常容易添加、刪除和修改具體類,甚至在修改接口或抽象類時,也不需要修改客戶端源代碼。這使得建造者模式成為最強大的模式之一,它可以在許多場景下使用。這并不是說,它總是比工廠模式更好。對于簡單的對象,工廠模式通常是最好的選擇。當然,模式存在于不同的尺度上,工廠模式嵌套在建造者模式中并不罕見,反之亦然。

主站蜘蛛池模板: 许昌市| 德化县| 巴东县| 水富县| 双柏县| 邳州市| 遵义县| 东光县| 信阳市| 霸州市| 哈尔滨市| 庆城县| 甘南县| 洛宁县| 迭部县| 湖南省| 昔阳县| 临邑县| 祁阳县| 滦平县| 伊春市| 峡江县| 马鞍山市| 青川县| 门头沟区| 巍山| 太白县| 贺兰县| 渭源县| 新野县| 芜湖县| 包头市| 岳普湖县| 正安县| 宿松县| 桑日县| 芦山县| 乌鲁木齐市| 商南县| 花垣县| 江华|