硬肝系列:23种设计模式之建造者模式

用示例代码来帮你了解建造者模式

对于“设计模式”这个词大家肯定都不陌生,很多框架也用到了设计模式,但是大部分的开发者应该是没有深入的了解过,我准备硬肝下这23设计模式作为专题文章的开端,一共23种设计模式,我尽量在<23天肝完。

为什么要学习设计模式:https://blog.csdn.net/kaituozhe_sh/article/details/107922339

在我大学四年,对设计模式也没有什么概念,写代码就想着能实现就可以了,不会有设计模式那样的思想,但是当学习到了框架的时候,对于设计模式才有了一些更深入的了解,使用设计模式的代码在扩展性上会比暴力的代码更容易维护,特别是当一个程序猿离职了后,你去接手它的代码,里面是一大堆if else,这样真的会崩溃,修改都不知道从何下手
在这里插入图片描述

硬肝系列目录

创建型模式

23种设计模式之工厂模式

23种设计模式之抽象工厂模式

23种设计模式之建造者模式

23种设计模式之原型模式

23种设计模式之单例模式

结构型模式

23种设计模式之适配器模式

23种设计模式之桥梁模式

23种设计模式之代理模式

23种设计模式之外观模式

23种设计模式之装饰器模式

23种设计模式之享元模式

23种设计模式之组合模式

行为型模式

23种设计模式之责任链模式

23种设计模式之命令模式

23种设计模式之迭代器模式

23种设计模式之中介者模式

23种设计模式之备忘录模式

2021/3/16原版

一、为什么要使用建造者模式?
现如今需求的不断变化,类中参数的不断增多,对于构造方法来说的确不太友好;用一个例子来说明吧,对于麦当劳来说,这么多种类的食物可以根据购买者来自主选择搭配,如果用普通的构造方法来实现的话,这样搭配的种类就非常多了,这时候我们就可以选择一种设计模式,也就是建造者模式,建造者模式(在创建一个对象的时 我们并不直接对操作对象,而是通过Builder类来存储参数,这个类往往就是建造类。

看看下面一个通过静态内部类实现的例子

用途:使得类可以以链式方法实例化对象

意义:其实现是静态内部类的典型应用,可以让大家很好理解静态内部类的意义

package designModels.BuilderModel03.model01;

public class McDonald {
    //汉堡
    private int hamburger;
    //双层汉堡
    private int doubleHamburger;
    //玉米棒
    private int corn;
    //辣翅
    private int spicyChicken;
    //汉堡
    private int fishBurger;
    //可口可乐
    private int cocaCola;
    //新建一个内部Builder类,来预存传过来的食物
    public static class Builder{
        //汉堡
        private int hamburger;
        //双层汉堡
        private int doubleHamburger;
        //玉米棒
        private int corn;
        //辣翅
        private int spicyChicken;
        //汉堡
        private int fishBurger;
        //可口可乐
        private int cocaCola;
        public Builder(){}

        public int getHamburger() {
            return hamburger;
        }

        public Builder BuilderHamburger(int hamburger) {
            this.hamburger = hamburger;
            System.out.println("加" + hamburger + " 个汉堡");
            return this;
        }

        public int getDoubleHamburger() {
            return doubleHamburger;
        }

        public Builder BuilderDoubleHamburger(int doubleHamburger) {
            this.doubleHamburger = doubleHamburger;
            System.out.println("加" + doubleHamburger + " 个双层汉堡");
            return this;
        }

        public int getCorn() {
            return corn;
        }

        public Builder BuilderCorn(int corn) {
            this.corn = corn;
            System.out.println("加" + corn + " 根玉米棒");
            return this;
        }

        public int getSpicyChicken() {
            return spicyChicken;
        }

        public Builder BuilderSpicyChicken(int spicyChicken) {
            this.spicyChicken = spicyChicken;
            System.out.println("加" + spicyChicken + " 对辣翅");
            return this;
        }

        public int getFishBurger() {
            return fishBurger;
        }

        public Builder BuilderFishBurger(int fishBurger) {
            this.fishBurger = fishBurger;
            System.out.println("加" + fishBurger + " 个鳕鱼堡");
            return this;
        }

        public int getCocaCola() {
            return cocaCola;
        }

        public Builder BuilderCocaCola(int cocaCola) {
            this.cocaCola = cocaCola;
            System.out.println("加" + cocaCola + " 杯cocaCola");
            return this;
        }
        //点完餐后调用此方法,新建外部类对象,将预存的信息作为入参
        //传输给外部类构造方法
        public McDonald build(){
            return new McDonald(this);
        }
    }

	//接收内部类传过来的参数
    private McDonald(Builder builder) {
        this.hamburger = builder.hamburger;
        this.doubleHamburger = builder.doubleHamburger;
        this.corn = builder.corn;
        this.spicyChicken = builder.spicyChicken;
        this.fishBurger = builder.fishBurger;
        this.cocaCola = builder.cocaCola;
    }

    public static void main(String[] args) {
        McDonald builder = new McDonald.Builder().BuilderCocaCola(2)
                .BuilderCorn(2).BuilderDoubleHamburger(1).build();
    }
}

打印结果:

2 杯cocaCola
加2 根玉米棒
加1 个双层汉堡

使用一个建造类来帮我们预存信息,当预存完毕时即可将所预存的信息传到外部类作为入参,即可获取到预存的信息。

上面这种方式实现建造者模式缺陷还是很大的,所以我下面又将它进行了一个小改造
新建一个食物接口:

package designModels.BuilderModel03.model02;

import java.math.BigDecimal;

public interface Food {
    String name();
    BigDecimal price();
}

食物接口的定义,就将所有食物都做了一个规范,下面为接口实现类

import designModels.BuilderModel03.model02.Food;

import java.math.BigDecimal;
//可乐
public class cocaCola implements Food {
    @Override
    public String name() {
        return "cocaCola";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(13);
    }
}
//玉米棒
public class corn implements Food {
    @Override
    public String name() {
        return "corn";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(16);
    }
}
//双层汉堡
public class doubleHamburger implements Food {
    @Override
    public String name() {
        return "doubleHamburger";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(52);
    }
}
//鳕鱼堡
public class fishBurger implements Food {
    @Override
    public String name() {
        return "fishBurger";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(32);
    }
}
//汉堡
public class hamburger implements Food {
    @Override
    public String name() {
        return "hamburger";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(36);
    }
}
//辣翅
public class spicyChicken implements Food {
    @Override
    public String name() {
        return "spicyChicken";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(18);
    }
}

定义一菜单接口:

package designModels.BuilderModel03.model02;

public interface McMenu {
	//入参为food,food里面包含了多种食物的信息
    McMenu append(Food food);
    //打印菜单
    String printMenu();
}

建造类(菜单实现类)

package designModels.BuilderModel03.model02.impl;

import designModels.BuilderModel03.model02.McMenu;
import designModels.BuilderModel03.model02.Food;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class Builder implements McMenu {
    List<Food> foodList = new ArrayList<>();
    BigDecimal price = new BigDecimal(0);
    @Override
    public McMenu append(Food food) {
        foodList.add(food);
        price = price.add(food.price());
        return this;
    }

    @Override
    public String printMenu() {
        StringBuilder str = new StringBuilder();
        for (Food food:foodList) {
            str.append("食品名称:" + food.name() + "----- 单价:" + food.price() + "\n");
        }
        str.append("all price :" + price);
        return str.toString();
    }

    public static void main(String[] args) {
        String menu = new Builder().append(new cocaCola()).append(new corn()).append(new fishBurger()).printMenu();
        System.out.println(menu);
    }
}

打印结果:

食品名称:cocaCola----- 单价:13
食品名称:corn----- 单价:16
食品名称:fishBurger----- 单价:32
all price :61

在一些基本的原料基本不变、组合经常变化的情况下,我们就可以使用这种建造者设计模式来实现

完成:TO: 2021/3/16 16:33

2021/3/22第一次修改

今天看文章的时候注意到了一个问题,建造者模式应该是用户的重点为最终的结果、且不知道建造内部的细节,而我我原来写的食物搭配的例子容易引起误会,因为这种搭配是呈现在客户眼前的,他知道了其中的细节,这里我再给大家举一个例子,也是以汉堡为例,我做一包薯条,建造者模式的意思就是说我不管你怎么做的,你最后给我一包汉堡就行

首先定义一个制作汉堡步骤接口

public interface Hamburger {
    void step1();
    void step2();
    void step3();
    void step4();
}

创建汉堡类并实现上面的接口

public class HamburgerImpl implements Hamburger{
    @Override
    public void step1() {
        System.out.println("准备面包");
    }

    @Override
    public void step2() {
        System.out.println("准备菜叶子");
    }

    @Override
    public void step3() {
        System.out.println("准备肉排");
    }

    @Override
    public void step4() {
        System.out.println("组合蟹黄堡");
    }
    private static class Builder{
        public Builder(HamburgerImpl hamburger){
            hamburger.step1();
            hamburger.step2();
            hamburger.step3();
            hamburger.step4();
            System.out.println("可以售卖");
        }
    }
}

测试代码

public static void main(String[] args) {
        Builder builder = new Builder(new HamburgerImpl());
    }

实现结果

准备面包
准备菜叶子
准备肉排
组合蟹黄堡
可以售卖
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉淀顶峰相见的PET

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值