104建造者模式

1建造者模式简介

建造者模式(Builder Pattern)也叫做生成器模式,其定义如下: Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)

建造者模式可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象

建造者模式是一步步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节

当需要实例化一个复杂的类,以得到不同结构和不同内部状态的对象时,我们可以使用不同的类对它们的实例化操作逻辑分别进行封装,这些类就被称为建造者。每当需要来自同一个类但具有不同结构的对象时,就可以通过构造另一个建造者来进行实例化。

基本类图为

该模式包含的角色有:

  • Product(产品类):需要为其构建对象的类,是具有不同表现形式的复杂或复合对象。
  • Builder(抽象建造者类):用于声明构建产品类的组成部分的抽象类或接口。它的作用是仅公开构建产品类的功能,隐藏产品类的其他功能;将产品类与构建产品类的更高级的类分离开。
  • ConcreteBuilder(具体建造者类):用于实现抽象建造者类接口中声明的方法,构建和装配各个部件。
  • Director(导演类):构建一个Builder接口的对象,它主要是用于创建一个复杂的对象。作用:①隔离调用Client类与对象的生产过程,②负责控制产品对象的生产过程

通用源码

//产品类
//通常是实现了模板方法模式
public class FastFoodClient {
    public static void main(String[] args) {
        //肯德基生产快餐
        FastFoodDirector director1 = new FastFoodDirector();
        KFCFastFoodModel kfcFastFoodModel1 = director1.getKFCFastFoodModel1();
        kfcFastFoodModel1.production();
        System.out.println("------------");
        KFCFastFoodModel kfcFastFoodModel2 = director1.getKFCFastFoodModel2();
        kfcFastFoodModel2.production();
        //麦当劳生产快餐  不在演示
    }
}
//抽象建造者
//规范产品的组建,一般是由子类实现
public abstract class Builder {    
     //设置产品的不同部分,以获得不同的产品
     public abstract void setPart();
     //建造产品
     public abstract Product buildProduct();
}
//具体建造者
//实现抽象类定义的所有方法,并且返回一个组建好的对象
public class ConcreteProduct extends Builder {
     private Product product = new Product();
     //设置产品零件
     public void setPart(){
             /*
              * 产品类内的逻辑处理
              */
     }  
     //组建一个产品
     public Product buildProduct() {
             return product;
     }
}
//导演类
//负责安排已有模块的顺序
public class Director {
     private Builder builder = new ConcreteProduct();
     //构建不同的产品
     public Product getAProduct(){
             builder.setPart();
             /*
              * 设置不同的零件,产生不同的产品
              */
             return builder.buildProduct();
     }
}

2传统方式

需求:快餐店生产食物,食物有饮品、汉堡包、小吃、薯条等,现在有麦当劳、肯德基、华莱士等等快餐店,各个店的食物大体相同,但是步骤不一定相同

传统方式现实快餐店生产食物需求

//产品模板类 快餐生产店
public abstract class FastFoodModel {
    //饮品
    protected abstract void drink();
    //汉堡
    protected abstract void hamburger();
    //小吃
    protected abstract void snack();
    //薯条
    protected abstract void chips();
    //生产快餐
    public void production(){
        drink();
        hamburger();
        snack();
        chips();
    }
}

public class KFCFastFoodModel extends FastFoodModel{
    @Override
    protected void drink() {
        System.out.println("肯德基生产饮品");
    }

    @Override
    protected void hamburger() {
        System.out.println("肯德基生产汉堡包");
    }

    @Override
    protected void snack() {
        System.out.println("肯德基生产小吃");
    }

    @Override
    protected void chips() {
        System.out.println("肯德基生产薯条");
    }
}

public class MCDFastFoodModel extends FastFoodModel{
    @Override
    protected void drink() {
        System.out.println("麦当劳生产饮品");
    }

    @Override
    protected void hamburger() {
        System.out.println("麦当劳生产汉堡包");
    }

    @Override
    protected void snack() {
        System.out.println("麦当劳生产小吃");
    }

    @Override
    protected void chips() {
        System.out.println("麦当劳生产薯条");
    }
}

调用Client类

public class FastFoodClient {
    public static void main(String[] args) {
        //肯德基生产快餐
        FastFoodModel kfcFood = new KFCFastFoodModel();
        kfcFood.production();
        //麦当劳生产快餐
        FastFoodModel mcdFood = new MCDFastFoodModel();
        mcdFood.production();
    }
}

 以上需求实现的弊端:当某店的食材(土豆)没有的话,就没法生产薯条,production()生产方法不够灵活,并且麦当劳和肯德基生产食材的步骤不一定相等

3建造者模式实现

根据上述代码弊端,所以为每个产品提供一个建造者的角色,想生产什么直接让建造者控制,在增加Director类,负责按照指定的顺序生产模型

//产品模板类 快餐生产店
public abstract class AbsFastFoodModel {
    //定义各个基本方法执行的顺序
    private ArrayList<String> sequence = new ArrayList<String>();
    //饮品
    protected abstract void drink();
    //汉堡
    protected abstract void hamburger();
    //小吃
    protected abstract void snack();
    //薯条
    protected abstract void chips();
    //生产快餐
    public void production(){
        for (int i = 0; i < sequence.size(); i++) {
            if (sequence.get(i).equals("drink")){
                drink();
            }else if (sequence.get(i).equals("hamburger")){
                hamburger();
            }else if (sequence.get(i).equals("snack")){
                snack();
            }else if (sequence.get(i).equals("chips")){
                chips();
            }
        }

    }
    //把传递过来的值传递到类内
    public void setSequence(ArrayList sequence){
        this.sequence = sequence;
    }

}
public class KFCFastFoodModel extends AbsFastFoodModel {
    @Override
    protected void drink() {
        System.out.println("肯德基生产饮品");
    }

    @Override
    protected void hamburger() {
        System.out.println("肯德基生产汉堡包");
    }

    @Override
    protected void snack() {
        System.out.println("肯德基生产小吃");
    }

    @Override
    protected void chips() {
        System.out.println("肯德基生产薯条");
    }
}

public class MCDFastFoodModel extends AbsFastFoodModel {
    @Override
    protected void drink() {
        System.out.println("麦当劳生产饮品");
    }

    @Override
    protected void hamburger() {
        System.out.println("麦当劳生产汉堡包");
    }

    @Override
    protected void snack() {
        System.out.println("麦当劳生产小吃");
    }

    @Override
    protected void chips() {
        System.out.println("麦当劳生产薯条");
    }
}
//构建者基类
public abstract class AbsFastFoodBuilder {
    public abstract void setSequence(ArrayList sequence);//设置组装 生产顺序
    public abstract AbsFastFoodModel getFastFoodModel();//获取产品类
}
public class KFCFastFoodBuilder extends AbsFastFoodBuilder{
    private KFCFastFoodModel kfcFastFoodModel = new KFCFastFoodModel();
    @Override
    public void setSequence(ArrayList sequence) {
        kfcFastFoodModel.setSequence(sequence);
    }

    @Override
    public AbsFastFoodModel getFastFoodModel() {
        return kfcFastFoodModel;
    }
}

public class MDCFastFoodBuilder extends AbsFastFoodBuilder{
    private MCDFastFoodModel mcdFastFoodModel = new MCDFastFoodModel();
    @Override
    public void setSequence(ArrayList sequence) {
        mcdFastFoodModel.setSequence(sequence);
    }

    @Override
    public AbsFastFoodModel getFastFoodModel() {
        return mcdFastFoodModel;
    }
}

导演类

//导演类 控制对象的生产过程
public class FastFoodDirector {

    private KFCFastFoodBuilder kfcFastFoodBuilder = new KFCFastFoodBuilder();
    private MDCFastFoodBuilder mdcFastFoodBuilder = new MDCFastFoodBuilder();
    //该方法可以设置 生产的套餐顺序
    public KFCFastFoodModel getKFCFastFoodModel1(){
        ArrayList<String> sequence = new ArrayList<String>();
        sequence.add("drink");
        sequence.add("hamburger");
        sequence.add("snack");
        sequence.add("chips");
        kfcFastFoodBuilder.setSequence(sequence);
        return (KFCFastFoodModel) kfcFastFoodBuilder.getFastFoodModel();
    }
    public KFCFastFoodModel getKFCFastFoodModel2(){
        ArrayList<String> sequence = new ArrayList<String>();
        sequence.add("drink");
        sequence.add("hamburger");
        sequence.add("snack");
        kfcFastFoodBuilder.setSequence(sequence);
        return (KFCFastFoodModel) kfcFastFoodBuilder.getFastFoodModel();
    }
    public MCDFastFoodModel getMDCFastFoodBuilder1(){
        ArrayList<String> sequence = new ArrayList<String>();
        sequence.add("drink");
        sequence.add("hamburger");
        sequence.add("snack");
        sequence.add("chips");
        kfcFastFoodBuilder.setSequence(sequence);
        return (MCDFastFoodModel) mdcFastFoodBuilder.getFastFoodModel();
    }
    public MCDFastFoodModel getMDCFastFoodBuilder2(){
        ArrayList<String> sequence = new ArrayList<String>();
        sequence.add("drink");
        sequence.add("hamburger");
        sequence.add("snack");
        sequence.add("chips");
        kfcFastFoodBuilder.setSequence(sequence);
        return (MCDFastFoodModel) mdcFastFoodBuilder.getFastFoodModel();
    }
}

Client类

public class FastFoodClient {
    public static void main(String[] args) {
        //肯德基生产快餐
        FastFoodDirector director1 = new FastFoodDirector();
        KFCFastFoodModel kfcFastFoodModel1 = director1.getKFCFastFoodModel1();
        kfcFastFoodModel1.production();
        System.out.println("------------");
        KFCFastFoodModel kfcFastFoodModel2 = director1.getKFCFastFoodModel2();
        kfcFastFoodModel2.production();
        //麦当劳生产快餐  不在演示
    }
}

注:上述代码结合了模板模式(所以代码量比较多)

总结:①封装性:使用建造者模式可以使客户端不必知道产品内部组成的细节,如例子中我们就不需要关心每一个具体的模型内部是如何实现的,产生的对象类型就是AbsFastFoodModel。

②建造者独立,容易扩展,KFCFastFoodBuilder和MDCFastFoodBuilder是相互独立的,对系统的扩展非常有利。

③具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响

使用场景:

  • 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。

建造者和工厂模式的区别:

  • 都是创建型模式
  • 建造者模式这是它与工厂方法模式最大不同的地方,
  • 建造者模式关注的是零件类型和装配工艺(顺序),最主要的功能是基本方法的调用顺序安排,零件的装配,装配的顺序不同产生的对象也不同
  • 工厂方法重点是创建,创建零件是它的主要职责,组装顺序则不是它关心的。

jdk中的StringBuilder采用了建造者模式

  • Appendable接口定义了多个append抽象方法,Appendable为抽象建造者,定义了抽象方法
  • AbstractStringBuilder实现了Appendable接口,充当建造者角色,只是不能实例化
  • StringBuilder同时充当了导演类和具体的建造者,
  • 调用api的人充当Client角色
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值