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

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

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

为什么要学习设计模式:https://blog.youkuaiyun.com/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());
    }

实现结果

准备面包
准备菜叶子
准备肉排
组合蟹黄堡
可以售卖
资源下载链接为: https://pan.quark.cn/s/dab15056c6a5 用户画像(User Profile)是大数据领域关键概念,是基于用户多维度信息如行为数据、偏好、习惯等构建的虚拟代表。它是数据分析重要工具,能助企业深度理解用户,实现精准营销、个性化推荐及服务优化。其源码涵盖以下内容:一是数据收集,需大量数据支撑,常借助Flume、Kafka等日志收集系统,实时或批量收集用户浏览记录、购买行为、搜索关键词等数据;二是数据处理与清洗,因数据源杂乱,需用Hadoop、Spark等大数据处理框架预处理,去除噪声数据,统一格式,保障数据质量;三是特征工程,为构建用户画像关键,要挑选有意义特征,像用户年龄、性别、消费频率等,且对特征编码、标准化、归一化;四是用户聚类,用K-means、DBSCAN等算法将用户分组,找出行为模式相似用户群体;五是用户建模,借助决策树、随机森林、神经网络等机器学习模型对用户建模,预测其行为或需求;六是用户画像生成,把分析结果转为可视化用户标签,如“高消费能力”、“活跃用户”等,方便业务人员理解。 其说明文档包含:一是项目背景与目标,阐述构建用户画像原因及期望效果;二是技术选型,说明选用特定大数据处理工具和技术栈的理由;三是数据架构,描述数据来源、存储方式(如HDFS、数据库)及数据流图等;四是实现流程,详述各步骤操作方法和逻辑,含代码解释及关键函数功能;五是模型评估,介绍度量用户画像准确性和有效性方式,像准确率、召回率、F1分数等指标;六是应用场景,列举用户画像在个性化推荐、广告定向、客户服务等实际业务中的应用;七是注意事项,分享开发中遇问题、解决方案及优化建议;八是结果展示,以图表、报表等形式直观呈现用户画像成果,展现用户特征和行为模式。 该压缩包资源对学习实践用户画像技术价值大,既可助人深入理解构建过程,又能通过源码洞察大数据处
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

沉淀顶峰相见的PET

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

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

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

打赏作者

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

抵扣说明:

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

余额充值