zoukankan      html  css  js  c++  java
  • 设计模式

    建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

    介绍

    • 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
    • 主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
    • 何时使用:一些基本部件不会变,而其组合经常变化的时候
    • 如何解决:将变与不变分离开
    • 关键代码:
      • 建造者:创建和提供实例
      • 导演:管理建造出来的实例的依赖关系
    • 应用实例:
      1. 去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"
      2. JAVA 中的 StringBuilder
    • 优点:
      1. 建造者独立,易扩展
      2. 便于控制细节风险
    • 缺点:
      1. 产品必须有共同点,范围有限制
      2. 如内部变化复杂,会有很多的建造类
    • 使用场景:
      1. 需要生成的对象具有复杂的内部结构
      2. 需要生成的对象内部属性本身相互依赖
    • 注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序

    实现

    假设一个快餐店的案例:一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)

    • 汉堡: 可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中
    • 冷饮: 可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中

    • 思路

      1. 创建一个表示食物种类的 Item 接口和实体类
      2. 创建一个表示食物包装的 Packing 接口和实体类,汉堡是包在纸盒中,冷饮是装在瓶子中
      3. 创建一顿饭Meal的实体类,以及制造一顿饭的实现类MealBuilder(其实就是把不同的食物组合到一起构成一个Meal)
      4. 最后是测试类

    1. 创建食物类型 和 食物包装的接口

    /**
     * 食物种类接口
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public interface Item {
        
        /**
         * 名称
         * @return
         */
        public String name();
        
        /**
         * 价格
         * @return
         */
        public float price();
        
        /**
         * 包装
         * @return
         */
        public Packing packing();
    }
    
    /**
     * 食物包装接口
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public interface Packing {
        
        /**
         * 包装
         * @return
         */
        public String pack();
    }
    

    2. 创建包装接口的实现类

    /**
     * 瓶子包装实体类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class Bottle implements Packing {
    
        @Override
        public String pack() {
            
            return "Bottle";
        }
    }
    
    /**
     * 纸盒包装实体类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class Wrapper implements Packing {
    
        @Override
        public String pack() {
            
            return "Wrapper";
        }
    }
    

    3. 创建食物种类接口的抽象类

    因为食物的种类比较繁多,但每种食物均有共同的属性,所以抽出一层抽象类

    /**
     * 汉堡食物抽象类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public abstract class Burger implements Item {
        
        /**
         * 价格
         * @return
         */
        @Override
        public abstract float price();
        
        /**
         * 包装
         * @return
         */
        @Override
        public Packing packing() {
            
            return new Wrapper();
        }
    }
    
    /**
     * 冷饮食物抽象类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public abstract class ColdDrink implements Item {
        
        /**
         * 价格
         * @return
         */
        @Override
        public abstract float price();
        
        /**
         * 包装
         * @return
         */
        @Override
        public Packing packing() {
            
            return new Bottle();
        }
    }
    

    4. 创建具体食物的实体类

    /**
     * 素食汉堡食物实体类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class VegBurger extends Burger {
    
        @Override
        public String name() {
            
            return "Veg Burger";
        }
    
        @Override
        public float price() {
            
            return 10.0f;
        }
    }
    
    /**
     * 鸡肉汉堡食物实体类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class ChickenBurger extends Burger {
    
        @Override
        public String name() {
            
            return "Chicken Burger";
        }
    
        @Override
        public float price() {
            
            return 20.0f;
        }
    }
    
    /**
     * 可口可乐食物实体类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class Coke extends ColdDrink {
    
        @Override
        public String name() {
            
            return "Coke";
        }
    
        @Override
        public float price() {
            
            return 5.0f;
        }
    }
    
    /**
     * 百事可乐食物实体类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class Pepsi extends ColdDrink {
    
        @Override
        public String name() {
            
            return "Pepsi";
        }
    
        @Override
        public float price() {
            
            return 5.0f;
        }
    }
    

    5. 创建一顿饭的实体类

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 一顿饭 实体类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class Meal {
        
        private List<Item> listItems = new ArrayList<Item>();
        
        /**
         * 增加食物
         * @param item
         */
        public void addItem(Item item) {
            listItems.add(item);
        }
        
        /**
         * 获取这顿饭的价格
         * @return
         */
        public float getPrice() {
            
            float price = 0;
            
            for(Item item : listItems) {
                price += item.price();
            }
            
            return price;
        }
        
        /**
         * 查看这顿饭的内容
         */
        public void showItems() {
            for(Item item : listItems) {
                System.out.println("Item : "+item.name()+", "+item.packing().pack()+", "+item.price());
            }
        }
    }
    

    6. 制造一顿饭(其实就是把各种食物组合到一起)

    /**
     * 建造一顿饭
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class MealBuilder {
        
        /**
         * 准备一顿素食餐
         * @return
         */
        public Meal prepareVegMeal() {
            
            Meal meal = new Meal();
            meal.addItem(new VegBurger());
            meal.addItem(new Coke());
            
            return meal;
        }
        
        /**
         * 准备一顿非素食餐
         * @return
         */
        public Meal prepareNonVegMeal() {
            
            Meal meal = new Meal();
            meal.addItem(new ChickenBurger());
            meal.addItem(new Pepsi());
            
            return meal;
        }
    }
    

    7. 建造者模式的测试类

    /**
     * 建造者模式 测试类
     * @author remainsu
     * @version 1.0 2019-06-13
     */
    public class Test {
        
        public static void main(String[] args) {
            
            MealBuilder mealBuilder = new MealBuilder();
            
            Meal vegMeal = mealBuilder.prepareVegMeal();
            System.out.println("------Veg Meal------");
            vegMeal.showItems();
            System.out.println("Price : "+ vegMeal.getPrice());
            
            System.out.println();
            
            Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
            System.out.println("------Non Veg Meal------");
            nonVegMeal.showItems();
            System.out.println("Price : "+ nonVegMeal.getPrice());
        }
    }
    

    运行结果:

    ------Veg Meal------
    Item : Veg Burger, Wrapper, 10.0
    Item : Coke, Bottle, 5.0
    Price : 15.0
    
    ------Non Veg Meal------
    Item : Chicken Burger, Wrapper, 20.0
    Item : Pepsi, Bottle, 5.0
    Price : 25.0
    

    参考

    1. https://www.runoob.com/design-pattern/builder-pattern.html
    Souviens Toi Que Tu Vas Mourir !
  • 相关阅读:
    git ignore 添加忽略文件
    python| 闭包函数及装饰器
    python | DRF 框架知识总览
    python | CHROME底层原理和HTTP协议
    python| css 背景图片虚化效果
    python | js 图片与base64互相转换
    python | Linux各目录及每个目录的详细介绍
    python | 解决Django+Vue前后端分离的跨域问题及关闭csrf验证
    python | Nginx负载均衡策略
    python | Linux 搭建Nginx+uWSGI+Django环境
  • 原文地址:https://www.cnblogs.com/remainsu/p/she-ji-mo-shi--jian-zao-zhe-mo-shi.html
Copyright © 2011-2022 走看看