还没用过建造者模式?这篇文章帮你搞定

还没用过建造者模式?这篇文章帮你搞定

首页模拟经营空闲建造者更新时间:2024-04-22
前言

我们知道,常见的设计模式通常分为三大类:创建型模式、行为型模式、结构型模式。今天我们来聊聊创建型模式中的建造者模式,关于它的使用场景、优缺点、组成部分、实战实例讲解以及在JDK中的运用。

工厂模式我们已经比较熟悉,主要用来将实例化对象提取出来,放到一个类中统一维护和管理,从而达到解耦、提高项目的扩展性和维护性。建造者模式的功能与工厂模式很相似,但侧重点不同。下面我们就来详细了解一下创建者模式。

建造者模式简介

创建者模式(Builder Pattern),也翻译作构建者模式,也有人通俗的称作生成器模式。官方定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

用大白话解释就是:将一个复杂的对象分解为多个简单的对象,然后一步一步构建形成产品。它主要是将变化部分与不变部分相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

就好比我们要组装一台电脑,需要 CPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件,这些部件是不变的,但根据自身经济情况和使用的场景不同,可选择每部分的不同配置。

像这么一个复杂的对象的构建,往往需要多个步骤来进行完成。而且每个步骤采用的硬件配置信息可能有所不同。同时,也并不是每个电脑都需要显示器或鼠标的。在通过代码演示上述场景之前,我们先来了解一下建造者模式通常包含的几个角色及功能。

结构与功能

建造者模式通常由四个角色组成:产品、抽象建造者、具体建造者、指挥者。

每个角色功能如下:

结构图如图所示:

模式的实现

作为开发人员,我们使用笔记本时,往往还会配置外置键盘、鼠标和外置显示器。此时,一整套电脑装备就包含了:笔记本电脑、鼠标、键盘、显示器。当然,根据个人的需求不同,有些人不需要鼠标,有些人不需要外置键盘,有些人不需要外置显示器,这就又构成了不同的产品。

先来定义产品类Computer,也就是开发电脑的整体配置:

public class Computer { /** * 笔记本电脑 */ private Laptop laptop; /** * 鼠标 */ private Mouse mouse; /** * 显示器 */ private Screen screen; /** * 键盘 */ private Keyboard keyboard; public void show() { System.out.println("笔记本配置:" laptop.getName()); System.out.println("鼠标配置:" mouse.getName()); System.out.println("显示器配置:" screen.getName()); System.out.println("键盘配置:" keyboard.getName()); } // 省略getter/setter方法 }

产品由四个组件构成:笔记本电脑、鼠标、显示器、键盘。

抽象建造者:包含创建产品各个子部件的抽象方法。通过接口声明在所有类型生成器中通用的产品构造步骤。

public interface ComputerBuilder { /** * 构建笔记本电脑 */ void constructLaptop(); /** * 构建鼠标 */ void constructMouse(); /** * 构建屏幕 */ void constructScreen(); /** * 构建键盘 */ void constructKeyboard(); /** * 返回最终产品对象 */ Computer getResult(); }

抽象建造者提供了每个组件构建的统一方法,至于具体每个组件内部的配置可能会有各种各样的变化,这就有具体的实现者来实现。

具体建造者:实现了抽象建造者接口。在当前业务场景中,我们假设公司给的电脑配置有两类,一类是普通的配置,一类是高端配置。这样就有两个具体的建造者了,用来提供构造过程的不同实现。

普通配置实现:

public class CommonComputerBuilder implements ComputerBuilder { private Computer computer = new Computer(); @Override public void constructLaptop() { Laptop laptop = new Laptop("A","华为笔记本"); computer.setLaptop(laptop); } @Override public void constructMouse() { Mouse mouse = new Mouse("A","无线鼠标"); computer.setMouse(mouse); } @Override public void constructScreen() { Screen screen = new Screen("A","液晶显示器"); computer.setScreen(screen); } @Override public void constructKeyboard() { Keyboard keyboard = new Keyboard("A","普通键盘"); computer.setKeyboard(keyboard); } @Override public Computer getResult() { return computer; } }

高级配置实现:

public class SupperComputerBuilder implements ComputerBuilder { private Computer computer = new Computer(); @Override public void constructLaptop() { Laptop laptop = new Laptop("S", "Mac Boor Pro"); computer.setLaptop(laptop); } @Override public void constructMouse() { Mouse mouse = new Mouse("A", "无线鼠标"); computer.setMouse(mouse); } @Override public void constructScreen() { Screen screen = new Screen("S", "液晶曲面屏"); computer.setScreen(screen); } @Override public void constructKeyboard() { Keyboard keyboard = new Keyboard("S", "机械键盘"); computer.setKeyboard(keyboard); } @Override public Computer getResult() { return computer; } }

在此具体建造者中,设置了每个组件的配置信息,这里做了简化,每个组件都只有类型和名称。而实际使用中,可能每个组件对象会包含不同的数据项。

指挥者:调用建造者中的方法完成复杂对象的创建。

public class Director { private ComputerBuilder builder; public Director(ComputerBuilder builder) { this.builder = builder; } //产品构建与组装方法 public Computer construct() { builder.constructLaptop(); builder.constructMouse(); builder.constructScreen(); builder.constructKeyboard(); return builder.getResult(); } }

指挥者对整个生产过程进行了封装,对客户端进行了隔离,客户端只用获得最终的产品即可,不用关心组装的过程。

客户端调用示例:

public class Client { public static void main(String[] args) { // 普通配置电脑的组装 ComputerBuilder builder = new CommonComputerBuilder(); Director director = new Director(builder); Computer product = director.construct(); product.show(); System.out.println("------------------"); // 高级配置电脑的组装 builder = new SupperComputerBuilder(); director = new Director(builder); product = director.construct(); product.show(); // 可拓展其他配置的构建中实现 } }

执行程序打印结果如下:

笔记本配置:华为笔记本 鼠标配置:无线鼠标 显示器配置:液晶显示器 键盘配置:普通键盘 ------------------ 笔记本配置:Mac Boor Pro 鼠标配置:无线鼠标 显示器配置:液晶曲面屏 键盘配置:机械键盘

针对上述实例,我们可以发现,如果还需要其他配置的电脑,只需要再创建一个Builder实现类即可,而指导类的组装顺序等也可以进行调整。在这种情况下对原有的功能也不会造成影响,符合设计模式中的开闭原则。

应用场景

适用场景其实才是理解设计模式最重要的,只有知道了适用于什么场景,才能够准确的使用设计模式。

根据上述实例可以看出,建造者(Builder)模式创建的是复杂对象,适用于面向产品的各个具体部分经常出现变化,但将它们组合在一起的算法却相对稳定的场景。

建造者模式适用于以下场景:

优点与缺点

通过上面的介绍,大概就可以了解到建造者模式的优缺点了。

优点:

建造者模式的缺点:

建造者(Builder)模式在应用过程中可以根据需要改变,如果创建的产品种类只有一种,只需要一个具体建造者,这时可以省略掉抽象建造者,甚至可以省略掉指挥者角色。

工厂模式VS建造者模式

建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,两者可以结合使用。

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

(1)建造者模式更加注重方法的调用顺序,工厂模式注重创建对象;

(2)创建对象的力度不同,建造者模式创建复杂的对象,有各种复杂的部件组成,工厂模式创建出来的对象都一样;

(3)关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还需要知道对象由哪些部件组成;

(4)建造者模式根据建造过程中顺序的不一样,最终的对象部件组成也不一样。

JDK中建造者的应用

我们最常用的StringBuilder类中就有建造者模式最直接的应用,看一下核心代码:

public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count len); str.getChars(0, len, value, count); count = len; return this; } @Override public StringBuilder append(char c) { super.append(c); return this; }

关于StringBuilder具体的接口继承等功能实现,可以对照上面的说明看一下源码实现。

小结

本篇文章带大家实践了一下建造者模式,详细介绍了它的构成与每部分的功能。关于设计模式,最重要的一点就是理解它们的应用场景,在适合的场景下使用合适的设计模式,同时还可以根据具体环境进行灵活的变通。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved