探索设计模式的魅力:一篇文章让你彻底搞懂建造者模式
建造者模式(Builder Pattern)是一种创建型设计模式,旨在将一个复杂对象的创建过程与其表示分离,使得同样的构建过程可以创建不同的表示形式。
主要角色:
产品(Product):表示正在构建的复杂对象。它由多个部分组成,这些部分可能具有不同的特性和属性。
抽象建造者(Abstract Builder):定义了构建产品所需的各个步骤抽象接口。每个步骤都有具体的实现方法,用于构建产品的不同部分。通常,抽象建造者还提供一个获取最终生成产品的方法。
具体建造者(Concrete Builder):实现了抽象建造者接口,负责实际构建产品的各个部分。具体建造者通常具有一个内部变量来保存当前产品的状态。构建过程中,具体建造者负责跟踪和更新产品的状态。
指挥者(Director):负责按特定顺序调用具体建造者的方法,以完成产品的构建过程。指挥者知道构建者应该如何构建产品,但不关心具体的构建细节。它通过接收具体建造者对象,按照预定的顺序调用构建步骤,最终获取完成的产品。
实现步骤:
定义产品类(Product):首先,定义一个需要被构建的复杂对象的类,这个类通常包含多个属性。
创建抽象建造者接口(Builder):建造者接口定义了用于构建产品的方法,这些方法包括设置产品的属性等。
创建具体建造者类(ConcreteBuilder):针对产品类实现抽象建造者接口,实现产品的各个部件的具体构造过程,以及提供获取最终产品的方法。
创建指挥者类(Director):指挥者类负责使用建造者接口来构建产品。它不直接构建产品,而是通过调用建造者接口中的方法来构建产品。
使用建造者模式:客户端代码通过指挥者类来构建产品,指挥者将构建过程委托给具体的建造者类,最终得到构建好的产品。
优点:
- 分离构建过程和最终表示:建造者模式可以将产品的构建过程与表示分离,使得相同的构建过程可以得到不同的表示。
- 易于扩展:通过建造者模式,可以很容易地扩展和改变产品的内部表示,使得我们可以更灵活地修改构建过程。
- 隐藏细节:客户端不需要关心产品的构建细节,只需关心最终的产品对象的使用即可。
- 构建复杂对象:对于构建具有复杂内部结构的对象来说,建造者模式可以使得构建过程更清晰、更易于维护。
缺点:
- 增加代码量:引入了建造者模式会增加代码量,特别是当产品的属性比较多,需要通过建造者类逐一设置时,会显得比较繁琐。
- 可能会导致产生多余的建造者对象:如果产品的构建过程比较简单,引入建造者模式可能会显得有些多余。
客户端(Client):创建指挥者对象并配置具体建造者,然后通过指挥者获取最终构建完成的产品。客户端可以根据需要选择不同的具体建造者或使用自定义的建造者。客户端只需要关心如何使用最终构建完成的产品。
建造者模式允许按照一系列步骤来构建对象,而不需要暴露复杂对象的构建过程。这种分步骤的构建方式使得构建过程更加灵活和可扩展,并且可以轻松地创建不同组合的对象。此外,建造者模式还可以避免创建过多的构造函数或重叠参数的问题。
建造者模式可以有效地解耦复杂对象的构建过程,提高灵活性和可维护性,同时还可以支持创建不同表示形式的产品。
目录
一、案例
1.1 示例代码
1.2 用建造者模式重写示例
二、模式讲解
2.1 功能
2.2 建造者模式的结构和说明
2.3 建造者模式重写代码的结构图
2.4 建造者模式的调用顺序示意图
3.5 相关模式
3.5.1 建造者模式和组合模式
3.5.2 建造者模式和模板方法模式
3.5.3 建造者模式和工厂方法模式
3.5.4 建造者模式与工厂模式
三、建造者模式结合抽象工厂模式
3.1 结合抽象工厂模式代码实现
3.2 练习
一、案例
在工厂模式中,我们抽象了工厂,客户端通过创建的工厂来实例化对应的产品。假设产A、产品B和 产品C 是流水线产品,流水线步骤一样(假设固定组装手机顺序:主板 -> 电池 -> 外壳 -> 调试 -> 包装),这时,工厂模式无法满足这种场景。
用建造者模式抽象流水线步骤实现。
1.1 示例代码
产品类:
class Product {// 产品的属性// ...
}
抽象建造者接口:
interface Builder {void buildPart1();void buildPart2();Product getResult();
}
具体建造者类:
class ConcreteBuilder implements Builder {private Product product = new Product();public void buildPart1() {// 构建产品的第一个部分// ...}public void buildPart2() {// 构建产品的第二个部分// ...}public Product getResult() {return this.product;}
}
指挥者:
class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public Product construct() {this.builder.buildPart1();this.builder.buildPart2();return this.builder.getResult();}
}
客户端:
public class Client {public static void main(String[] args) {Builder builder = new ConcreteBuilder();Director director = new Director(builder);Product product = director.construct();}
}
1.2 用建造者模式重写示例
产品类:(两个产品:小米和苹果)
@Data
public class XiaomiPhoneProduct {private String name = "小米";
}
@Data
public class ApplePhoneProduct {private String name = "苹果";
}
抽象建造者接口:
public interface Builder {/*** 组装主板*/void assembleMainboard();/*** 组装电池*/void assembleBattery();/*** 组装外壳*/void assembleOuter();/*** 调试*/void assembleDebugging();/*** 包装*/void assemblePack();}
小米建造者类:
public class XiaoMiBuilder implements Builder {private XiaomiPhoneProduct xm = new XiaomiPhoneProduct();@Overridepublic void assembleMainboard() {System.out.println("组装" + xm.getName() + "产品的 主板。");}@Overridepublic void assembleBattery() {System.out.println("组装" + xm.getName() + "产品的 电池。");}@Overridepublic void assembleOuter() {System.out.println("组装" + xm.getName() + "产品的 外壳。");}@Overridepublic void assembleDebugging() {System.out.println("调试" + xm.getName() + " 产品。");}@Overridepublic void assemblePack() {System.out.println("包装" + xm.getName() + " 产品。");}public XiaomiPhoneProduct getResult() {System.out.println("获取" + xm.getName() + "产品");return xm;}
}
苹果建造者类:
public class AppleBuilder implements Builder {private ApplePhoneProduct apple = new ApplePhoneProduct();@Overridepublic void assembleMainboard() {System.out.println("组装" + apple.getName() + "产品的 主板。");}@Overridepublic void assembleBattery() {System.out.println("组装" + apple.getName() + "产品的 电池。");}@Overridepublic void assembleOuter() {System.out.println("组装" + apple.getName() + "产品的 外壳。");}@Overridepublic void assembleDebugging() {System.out.println("调试" + apple.getName() + " 产品。");}@Overridepublic void assemblePack() {System.out.println("包装" + apple.getName() + " 产品。");}public ApplePhoneProduct getResult() {System.out.println("获取" + apple.getName() + "产品");return apple;}
}
指挥者:
public class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void construct() {// 组装主板this.builder.assembleMainboard();// 组装电池this.builder.assembleBattery();// 组装电池this.builder.assembleOuter();// 调试this.builder.assembleDebugging();// 包装this.builder.assemblePack();}
}
客户端:
public class Client {public static void main(String[] args) {XiaoMiBuilder xiaoMiBuilder = new XiaoMiBuilder();Director director1 = new Director(xiaoMiBuilder);// 组装小米手机产品director1.construct();// 获取小米手机XiaomiPhoneProduct result1 = xiaoMiBuilder.getResult();AppleBuilder appleBuilder = new AppleBuilder();Director director2 = new Director(appleBuilder);// 组装苹果手机产品director2.construct();// 获取苹果手机ApplePhoneProduct result2 = appleBuilder.getResult();}
}
测试支行:
组装小米产品的 主板。
组装小米产品的 电池。
组装小米产品的 外壳。
调试小米 产品。
包装小米 产品。
获取小米产品
组装苹果产品的 主板。
组装苹果产品的 电池。
组装苹果产品的 外壳。
调试苹果 产品。
包装苹果 产品。
获取苹果产品
通过上面的 讲述,应该能很清晰地看出建造者模式的实现方式和它的优势所在了,那就是对同 一个 构建过程,只要配置不同的建造者实现,就会生成不同表现的对象。
二、模式讲解
建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的 表示。
建造者模式的本质:分离整体构建算法和部件构造。
2.1 功能
功能:构建复杂的产品,而且是细化的、分步骤的构建产品,也就是建造者模式重在 一步 一步解决构造复杂对象的问题。不只为此,更为重要的是,这个构建的过程是统一的、固定不变的,变化的部分放到建造者部分了,只要配置不同的建造者,那么同样的构建过程,就能构建出不同的产品来。
2.2 建造者模式的结构和说明
- Builder:建造者接口,定义创建 一个Product 对象所需的各个部件的操作。
- ConcreteBuilder:具体的建造者实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。
- Director:指导者,也被称为导向者,主要用来使用Builder 接口,以一个统一的过程来构建所需要的Product 对象。
- Product:产品,表示被建造者构建的复杂对象,包含多个部件。
2.3 建造者模式重写代码的结构图
建造者模式主要用于以下几个方面的应用场景中:
构建复杂对象:当需要构建的对象具有复杂的内部结构,并且需要通过多个步骤逐步构建时,可以使用建造者模式。它可以将构建过程划分为多个步骤,每个步骤由具体的建造者来实现,从而更加灵活地构建复杂对象。
需要隐藏对象构建过程的细节:使用建造者模式可以将对象的构建细节隐藏起来,只向客户端暴露一个简单的构建接口。客户端不需要关心对象的具体构建过程,只需通过指挥者类来构建对象。
构建对象的部分属性可变:如果需要构建的对象具有一些可变的属性,而且构建过程中需要根据特定的需求来设置这些属性,可以使用建造者模式。建造者模式可以通过具体的建造者类,根据不同的需求来设置不同的属性值。
构建多个相似对象:如果有多个类似的对象需要构建,但是它们的构建过程略有不同,可以使用建造者模式。可以提供多个具体的建造者类来分别构建不同的对象,从而更好地组织和管理对象的构建过程。
优势:
简化对象的创建过程:通过建造者模式,可以将复杂对象的创建逻辑分解为多个步骤,使得构建过程更加清晰和可控。每个步骤都有对应的方法,在客户端代码中可以按需调用,不必关心具体的创建细节。
可以更灵活地构建对象:通过建造者模式,可以使用相同的构建过程来构建不同的产品。通过定义不同的具体建造者,可以创建具有不同属性配置的对象,而不会混淆或混合构建逻辑。
隐藏产品构建细节:客户端不需要了解产品的具体构建过程,可以直接通过指定建造者的方法来创建产品。这样可以减少客户端对产品内部细节的依赖,同时也可以隐藏产品内部的实现细节。
提供了更好的封装性:建造者模式将产品的创建过程封装在具体建造者中,客户端只需要调用指定的方法获取产品,而无需了解建造的细节。这种封装性可以减少对产品内部实现的直接访问,提高了代码的封装性和安全性。
支持逐步构建复杂对象:通过建造者模式,可以分步骤构建复杂对象。在每个步骤中,可以对对象进行逐渐完善和扩展,从而满足不同的需求和变化。
松散耦合:建造者模式可以用同一个构建算法构建出表现 上完全不同的产品,实现产品构建和产品表现 上的分离。建造者模式正是把产品构建的过程独立出来,使它和具体产品的表现松散耦合,从而使得构建算法可以复用,而具体产品表现也可以灵活地、方便地扩展和切换。
可以很容 易地改变产 品的内部表示:在建造者模式中,由 于Builder 对象只是提供接口给Director 使用,那么具体的部件创建和装配方式是被Builder 接口隐藏了的,Director 并不知道这些具体的实现细节。这样一来,要想改变产品的内部表示,只需要切换Builder 的具体实现即可,不用管Director,因此变得很容易。
更好的复用性:建造者模式很好地实现了构建算法和具体产品实现的分离。这样一来,使得构建产品的算法可以复用。同样的道理,具体产品的实现也可以复用,同一个产品的实现,可以配合不同的构建算法使用。
不足:
类的膨胀:使用建造者模式会引入额外的建造者类,导致类的数量增加。对于简单的对象,引入建造者模式可能会显得过度复杂。
对象内部结构的暴露:在一些情况下,建造者模式会要求产品对象暴露其内部结构,以便建造者能够逐步构建对象。这可能违反封装原则,并使得产品对象的内部结构对外暴露,降低了对象的安全性。
对象构建流程的不可逆转:一旦对象的构建过程开始,建造者模式往往不支持将构建过程逆转。一旦开始构建,很难回到前一个步骤进行修改。
不适合每个场景:建造者模式在对象的属性较多、复杂度较高,且对象的创建过程中涉及较多的选项和步骤时非常有用。但对于简单的对象,使用建造者模式可能会带来过多的额外复杂性。
学习和实现成本:建造者模式的实现需要定义产品类、抽象建造者、具体建造者等多个类,这可能带来额外的学习和实现成本,特别是对于初学者而言。
2.4 建造者模式的调用顺序示意图
3.5 相关模式
3.5.1 建造者模式和组合模式
这两个模式可以组合使用。
对于复杂的组合结构,可以使用建造者模式来一步一步构建。
3.5.2 建造者模式和模板方法模式
模板方法模式主要是用来定义算法的骨架,把算法中某些步骤延迟到子类中实现。再想起建造者模式 ,Director 用来定义整体的构建算法,把算法中某些涉及到具体部件对象的创建和装配的功能,委托给具体的Builder 来实现。
类似:
- 都是定义一个固定的算法骨架,然后把算法中的某些具体步骤 交给其他类来完成,都能 实现整体算法步骤和某些具体 步骤实现的分离。
区别:
- 模式的目的:建造者模式是用来构建复杂对象的,而模板方法是用来定义算法骨架,尤其是一些复杂的业务功能的处理算法的骨架;
- 模式的实现:建造者模式是采用委托的方法,而模板方法采用的是继承的方式;
- 使用的复杂度:建造者模式需要组合 Director 和Builder 对象,然后才能开始构建,要等构建完后才能得最终的对象,而模板方法就没有这么麻烦,直接使用子类对象即可。
3.5.3 建造者模式和工厂方法模式
这两个模式可以组合使用。
建造者模式的Builder 实现中,通常需要选择具体的部件实现。一个可行的方案就是实现成为工厂方法,通过工厂方法来获取具体的部件对象,然后再进行部件的装配。
3.5.4 建造者模式与工厂模式
1. 关注点不同:
- 工厂模式关注于创建对象的过程,即根据客户端请求创建相应的对象实例;
- 建造者模式关注于构建复杂对象的过程,即通过一步步构建的方式创建对象。
2. 设计目的不同:
- 工厂模式旨在解耦对象的创建和使用,在客户端和具体实现之间建立一个工厂类,通过工厂方法创建所需的对象实例;
- 建造者模式旨在通过一步步构建来创建一个复杂对象,也可以通过一系列构建步骤来定义不同的表示。
3. 灵活性不同:
- 工厂模式具有较高的灵活性,可以根据不同的需求创建不同类型的对象,且可以动态切换具体实现;
- 建造者模式相对固定,通常使用一个具体的构造类,按照固定步骤构建对象,不太容易切换。
4. 构建过程不同:
- 工厂模式的创建过程相对简单,仅涉及对象的实例化,没有复杂的构建过程;
- 建造者模式涉及多个步骤,每个步骤可以定制和配置,可以支持不同对象的创建。
三、建造者模式结合抽象工厂模式
回顾抽象工厂模式:
探索设计模式的魅力:抽象工厂模式的艺术-CSDN博客文章浏览阅读3.1k次,点赞67次,收藏68次。抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,用于在不指定具体类的情况下创建一系列相关或相互依赖的对象。它提供了一个接口,用于创建一系列“家族”或相关依赖对象,而无需指定它们的具体类。探索设计模式的魅力:简单工厂模式-CSDN博客实现简单工厂的难点就在于 “如何选择” 实现,前面便子中传递参数的方法, 那都是静态的参数,还可以实现成为动态的参数。https://blog.csdn.net/danci_/article/details/135638488
抽象工厂模式和建造者模式可以结合使用,以实现更复杂的对象创建过程。
3.1 结合抽象工厂模式代码实现
抽象工厂模式用于创建相关或依赖的对象族,而建造者模式用于创建复杂对象的构建过程。下面是一个示例,演示如何结合抽象工厂模式和建造者模式:
首先,定义产品族的抽象工厂接口,用于创建产品族中的不同类型产品。例如,我们可以创建一个汽车工厂接口来生产不同类型的汽车及其相关零部件。
public interface CarFactory {Engine createEngine();Wheel createWheel();// 其他相关方法
}
然后,定义具体的产品族工厂类,实现抽象工厂接口,并负责创建特定类型的产品。例如,我们可以创建一个奔驰汽车工厂类和一个宝马汽车工厂类。
public class BenzFactory implements CarFactory {@Overridepublic Engine createEngine() {return new BenzEngine();}@Overridepublic Wheel createWheel() {return new BenzWheel();}// 其他相关方法实现
}public class BMWFactory implements CarFactory {@Overridepublic Engine createEngine() {return new BMWEngine();}@Overridepublic Wheel createWheel() {return new BMWWheel();}// 其他相关方法实现
}
接下来,定义产品的抽象建造者接口,用于创建复杂对象。例如,我们可以创建一个汽车建造者接口来构建汽车对象。
public interface CarBuilder {void buildEngine();void buildWheel();// 其他构建方法Car getCar();
}
然后,定义具体的产品建造者类,实现抽象建造者接口,并负责实际构建复杂对象的各个部分。例如,我们可以创建一个汽车建造者类来构建汽车对象。
public class CarBuilderImpl implements CarBuilder {private Car car;public CarBuilderImpl() {this.car = new Car();}@Overridepublic void buildEngine() {// 构建引擎部分的具体逻辑// car.setEngine(...);}@Overridepublic void buildWheel() {// 构建轮子部分的具体逻辑// car.setWheel(...);}// 其他构建方法的具体实现@Overridepublic Car getCar() {return car;}
}
最后,在客户端中使用抽象工厂模式和建造者模式来创建复杂对象。
public class Client {public static void main(String[] args) {// 创建奔驰汽车工厂CarFactory benzFactory = new BenzFactory();// 创建汽车建造者CarBuilder builder = new CarBuilderImpl();// 设置建造者为奔驰工厂builder.setCarFactory(benzFactory);// 建造汽车并获取Car car = builder.buildCar();// 使用创建好的汽车car.drive();}
}
在这个例子中,我们通过抽象工厂模式创建了一个奔驰汽车工厂和一个宝马汽车工厂,并通过建造者模式创建了一个汽车对象。通过结合抽象工厂模式和建造者模式,我们可以实现更复杂的对象构建过程,并根据具体情况创建不同类型的对象。
3.2 练习
回顾工厂方法模式:
探索设计模式的魅力:工厂方法模式-CSDN博客文章浏览阅读6.3k次,点赞104次,收藏71次。工厂方法模式是一种创建型设计模式,它提供了一种创建对象的接口,但将具体实例化对象的工作推迟到子类中完成。这样做的目的是创建对象时不用依赖于具体的类,而是依赖于抽象,这提高了系统的灵活性和可扩展性。优点:降低耦合度、增加了系统的可扩展性 和 提高代码的可维护性;缺点:增加了代码的复杂性 和 需要更多的设计考虑。https://blog.csdn.net/danci_/article/details/135611783 请编程实现建造者模式结合工厂方法模式。
PS:感谢您耐心看到了这里,再麻烦动动发财的手,点个赞点个赞点个赞吧!(关注收藏也是免费的哦)
相关文章:
探索设计模式的魅力:一篇文章让你彻底搞懂建造者模式
建造者模式(Builder Pattern)是一种创建型设计模式,旨在将一个复杂对象的创建过程与其表示分离,使得同样的构建过程可以创建不同的表示形式。 主要角色: 产品(Product):表示正在构建…...

Facebook广告投放指南,如何运营多个Facebook广告账户不被封?
许多卖家做广告投放会选择 Facebook 作为主要的业务和产品推广平台。然而,要在这个竞争激烈的平台上脱颖而出并成功拓宽广告覆盖面并不容易,通常情况下大家会运营多个Facebook广告账号,但是很多人因此遭遇Facebook账号被封的情况,…...

音乐人声分离工具:极简的人声和背景音乐分离工具
项目地址:jianchang512/vocal-separate: an extremely simple tool for separating vocals and background music, completely localized for web operation, using 2stems/4stems/5stems models 这是一个极简的人声和背景音乐分离工具,本地化网页操作&a…...

Go语言基础快速上手
1、Go语言关键字 2、Go数据类型 3、特殊的操作 3.1、iota关键字 Go中没有明确意思上的enum(枚举)定义,不过可以借用iota标识符实现一组自增常亮值来实现枚举类型。 const (a iota // 0b // 1c 100 // 100d // 100 (与上一…...

Excel 根据日期按月汇总公式
Excel 根据日期按月汇总公式 数据透视表日期那一列右击,选择“组合”,步长选择“月” 参考 Excel 根据日期按月汇总公式Excel如何按着日期来做每月求和...

使用 crypto-js 进行 AES 加解密操作
在前端开发中,数据的加密和解密是为了保障用户隐私和数据的安全性而常见的任务。AES(Advanced Encryption Standard)是一种对称密钥加密算法,被广泛用于保护敏感信息的传输和存储。本文将介绍 AES 加解密的基本原理,并…...

Vue-30、Vue非单文件组件。
非单文件组件: 一个组件包含n个组件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>非单文件组件</title><script type"text/javascript" src"https://cdn.jsde…...

7-6 实验2_1_判断两数的大小
7-6 实验2_1_判断两数的大小 分数 100 全屏浏览题目 切换布局 作者 scs 单位 北京邮电大学 已知有两个整数,请使用if-else选择结构将它们中的较大数选择出来,存到max变量中;将较小数选择出来,存到min变量中,并将选…...

POKT Network (POKT) :进军百亿美元市场规模的人工智能推理市场
POKT Network(又称 Pocket Network)是一个去中心化的物理基础设施网络(DePIN),它能够协调并激励对任何开放数据源的访问,最初专注于向应用程序和服务提供商提供区块链数据。 自 2020 年主网上线以来&#x…...

【STM32】STM32学习笔记-I2C通信外设(34)
00. 目录 文章目录 00. 目录01. I2C简介02. I2C外设简介03. I2C框图04. I2C基本结构05. 主机发送06. 主机接收07. 软件/硬件波形对比08. 预留09. 附录 01. I2C简介 I2C(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式…...

从数据角度分析年龄与NBA球员赛场表现的关系【数据分析项目分享】
好久不见朋友们,今天给大家分享一个我自己很感兴趣的话题分析——NBA球员表现跟年龄关系到底大不大?数据来源于Kaggle,感兴趣的朋友可以点赞评论留言,我会将数据同代码一起发送给你。 目录 NBA球员表现的探索性数据分析导入Python…...

深入浅出Spring AOP
第1章:引言 大家好,我是小黑,咱们今天要聊的是Java中Spring框架的AOP(面向切面编程)。对于程序员来说,理解AOP对于掌握Spring框架来说是超级关键的。它像是魔法一样,能让咱们在不改变原有代码的…...

火速收藏!2024 新年微信红包封面领取全攻略
2024“龙”重登场!今年有哪些令人期待的红包封面? 前方大批精美红包封面来袭,全新品牌氛围红包封面上线,支持品牌定制特色氛围元素,沉浸感受浓浓年味儿,收获满满惊喜! 新年开好运,微…...

【RabbitMQ】RabbitMQ安装与使用详解以及Spring集成
🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《RabbitMQ实战》。🎯🎯 &am…...

企业多云组网怎么办?
在当今数字化时代,企业普遍采用多云策略,同时利用不同云平台的优势以实现成本优化和整体性能提升。根据Futuriom于2022年发布的“安全多云网络调查”报告,80%的受访者表示他们使用来自两个或更多公共云提供商的PaaS或IaaS产品。 多云策略的迅…...

背包问题(贪心) 二维01背包问题 Java
背包问题(贪心) 最优装载问题 题目描述 有n件物品和一个最大承重为w 的背包。第i件物品的重量是weight[i],每件只能用一次,求装入背包的最多物品数量。 题目分析 因为我们只要求装入物品的数量,所以装重的显然没有…...

2019年认证杯SPSSPRO杯数学建模D题(第二阶段)5G时代引发的道路规划革命全过程文档及程序
2019年认证杯SPSSPRO杯数学建模 D题 5G时代引发的道路规划革命 原题再现: 忙着回家或上班的司机们都知道交通堵塞既浪费时间又浪费燃料,甚至有的时候会带来情绪上的巨大影响,引发一系列的交通问题。据报道,每年交通拥堵使得美国…...

可视化k8s页面(Kubepi)
Kubepi是一个简单高效的k8s集群图形化管理工具,方便日常管理K8S集群,高效快速的查询日志定位问题的工具 随便在哪个节点部署,我这里在主节点部署 docker pull kubeoperator/kubepi-server docker run --privileged -itd --restartunless-st…...

1434. 数池塘(四方向)-深度优先搜索-DFS
代码: #include<iostream> using namespace std; char a[200][200]; int fx[4]{0,1,0,-1}; int fy[4]{1,0,-1,0}; int k0; int n,m; void dfs(int x,int y){a[x][y].;int tx,ty;for(int i0;i<4;i){txxfx[i];tyyfy[i];if(tx>1&&tx<n&&am…...

Mysql:重点且常用的操作和理论知识整理 ^_^
目录 1 基础的命令操作 2 DDL 数据库定义语言 2.1 数据库操作 2.2 数据表操作 2.2.1 创建数据表 2.2.2 修改和删除数据表 2.2.3 添加外键 3 DML 数据库操作语言 3.1 插入语句(INSERT) 3.2 修改语句(UPDATE) 3.3 删除语句 3.3.1 DELETE命令 3.3.2 TRUNCATE命令 4 …...

小车辅助脚本编写
小车辅助脚本编写 在远程控制中需要启动非常多的 Launch 文件,在终端启动很麻烦,编写一些脚本可以简化操作 robot_client.sh #!/bin/bashecho "开始执行Bash脚本"# 启动zedm roslaunch zed_wrapper zedm.launch & sleep 5# 启动realsen…...

Modern C++ 一个例子学习条件变量
目录 问题程序 施魔法让BUG浮出水面 条件变量注意事项 修改程序 问题程序 今天无意中看到一篇帖子,关于条件变量的,不过仔细看看发现它并达不到原本的目的。 程序如下,读者可以先想想他的本意,以及有没有问题: #…...

ora-12154无法解析指定的连接标识符
用户反映查询的时候报错ora-12154 这个系统只做历史数据查询使用,使用并不平凡,该数据库曾做过一次服务器间的迁移。 用户描述,所有oracle客户端查询该视图都报tns错误,一般ora-12154会发生在连接数据库时,因为tns配…...

rust跟我学三:文件时间属性获得方法
图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎样获得杀毒软件的病毒库时间的。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址…...

解决一个mysql的更新属性长度问题
需求背景: 线上有一个 platform属性,原有长度为 varchar(10),但是突然需要填入一个11位长度的值;而偏偏这个属性在线上100张表中有50张都存在,并且名字各式各样,庆幸都包含 platform;例如 platf…...

[网络安全]DHCP 部署与安全
一 、DHCP作用 (Dynamic HOst Configure Protocol ) 动态IP配置协议 作用:动态自动分配IP地址 二、DHCP相关概念 地址池/作用域: (IP、子网掩码、网关、DNS、周期) 三、DHCP优点 减少工程量 避免IP避免 提高地址利用率 四、DHCP原理 成为DHCP租约过程 步骤: 1.发送 DHC…...

自建ES集群
常用命令 # 重命名文件夹 mv elasticsearch-7.10.2 elasticsearch# 移动文件到文件夹 mv elasticsearch-7.10.2-linux-x86_64.tar.gz middleware-tar/ mv kibana-7.10.2-linux-x86_64.tar.gz middleware-tar/# 创建data文件夹 mkdir /home/admin/elasticsearch/data 自建Ela…...

git rev-parse v406 ‘v4.0.4‘^{} master什么意思?
git rev-parse 是一个 Git 命令,用于解析出 git 对象(如分支、标签、提交等)的完整 SHA-1 哈希值。这个命令对于理解 git 中各种引用的内部表示非常有用。 让我们一步步分析 git rev-parse v406 v4.0.4^{} master 这条命令: v406…...

AI 编程的机会和未来:从 Copilot 到 Code Agent
大模型的快速发展带来了 AI 应用的井喷。统计 GPT 使用情况,编程远超其他成为落地最快、使用率最高的场景。如今,大量程序员已经习惯了在 AI 辅助下进行编程。数据显示,GitHub Copilot 将程序员工作效率提升了 55%,一些实验中 AI …...

git push --set-upstream origin master时超时失败的解决方案
问题描述 提示:这里描述项目中遇到的问题: git push --set-upstream origin master时,超时失败,显示如下错误: connect to host git.acwing.com port 22: Connection timed out fatal: Could not read from remote …...