ビルダー
序文
誰もがビルダー モードに精通しているはずですが、コーディングのキャリアでは常にこのモードに遭遇します。Android 開発における AlertDialog、ネットワーク フレームワークにおける OkHttp と Retrofit、または JavaPoet には、そのような仲間がいます。
これが非常に人気がある理由は、開始の難易度が比較的低いことに加えて、オブジェクトの作成時に必要なパラメーターが多すぎるという日常の開発の問題を実際に解決してくれるためです。
小さな例を挙げてください
ここ数年、誰もがコインを投機するのが流行しており、市場でカードを見つけるのが困難になっています。政府の政策導入と仮想通貨の崩壊。グラフィックス カードはもはや貴重な状態ではありません。大学を卒業したばかりのシャオロンさんは、人々にコンピュータを提供することに特化したコンピュータ ショップを開きました。当初、要件は比較的単純で、コンピューターの CPU、GPU、ハードディスク、およびその他の関連情報のみが記録されていました。
オブジェクトを作成する伝統的な方法
// 电脑类
class Computer {
private String mBroad;
private String mCPU;
private String mGPU;
public Computer(String broad, String CPU, String GPU) {
mBroad = broad;
mCPU = CPU;
mGPU = GPU;
}
@Override
public String toString() {
return "Computer{" +
", mBroad='" + mBroad + ''' +
", mCPU='" + mCPU + ''' +
", mGPU='" + mGPU + ''' +
'}';
}
}
复制代码
このとき、次のように Computer オブジェクトを作成します。
Computer computer = new Computer("微星 B550M","INTEL I5","NV 3060TI");
复制代码
ビジネス量の増加に伴い、顧客の要求も増加しています。マウス、キーボード、およびシステムにも対応する要件があります。したがって、それに応じて Computer クラスを変更する必要がありました。
static class Computer {
private String mOS;
private String mBroad;
private String mKeyBoard;
private String mMouse;
private String mCPU;
private String mGPU;
public Computer(String OS, String broad, String keyBoard, String mouse, String CPU, String GPU) {
mOS = OS;
mBroad = broad;
mKeyBoard = keyBoard;
mMouse = mouse;
mCPU = CPU;
mGPU = GPU;
}
// 就写一个set方法否则文章太长,其他就不写了
public void setmBroad(String mBroad) {
this.mBroad = mBroad;
}
@Override
public String toString() {
return "Computer{" +
"mOS='" + mOS + ''' +
", mBroad='" + mBroad + ''' +
", mKeyBoard='" + mKeyBoard + ''' +
", mMouse='" + mMouse + ''' +
", mCPU='" + mCPU + ''' +
", mGPU='" + mGPU + ''' +
'}';
}
}
复制代码
そして、Computer オブジェクトを作成するためのパラメーターはますます長くなっています。
Computer computer = new Computer("MAC OS","微星 B550M","IQUNIX F97"
,"罗技 MX MASTER3","INTEL I5","NV 3060TI");
复制代码
新しい需要パラメータ、電源、シャーシ、放熱、メモリモジュール、ハードディスクがあるとしたら...想像することさえできません。
オブジェクト初期化パラメータの問題
この時点で、プログラミングでよくある問題に直面しています。オブジェクトに必要なパラメータが多すぎて、それらをすべてコンストラクタに渡すと、コンストラクタは例と同じで長すぎます。これを set メソッドで渡すと、さらに恐ろしいことになります。
この時モードが誕生し、彼はビルダーモードとなる。
ビルダーモードの処理
/**
* @author:TianLong
* @date:2022/10/17 19:58
* @detail:产品类
*/
class Computer{
private String mOS;
private String mBroad;
private String mKeyBoard;
private String mMouse;
private String mCPU;
private String mGPU;
private Computer(String OS, String broad, String keyBoard, String mouse, String CPU, String GPU) {
mOS = OS;
mBroad = broad;
mKeyBoard = keyBoard;
mMouse = mouse;
mCPU = CPU;
mGPU = GPU;
}
public static ComputerBuilder createBuilder(){
return new ComputerBuilder();
}
@Override
public String toString() {
return "Computer{" +
"mOS='" + mOS + ''' +
", mBroad='" + mBroad + ''' +
", mKeyBoard='" + mKeyBoard + ''' +
", mMouse='" + mMouse + ''' +
", mCPU='" + mCPU + ''' +
", mGPU='" + mGPU + ''' +
'}';
}
/**
* @author:TianLong
* @date:2022/10/17 19:58
* @detail:产品建造者类
*/
public static class ComputerBuilder{
private String mOS = "Windows";
private String mBroad= "微星 B550M";
private String mKeyBoard= "无";
private String mMouse= "无";
private String mCPU= "Intel I5";
private String mGPU= "AMD 6600XT";
public ComputerBuilder setOS(String OS) {
mOS = OS;
return this;
}
public ComputerBuilder setBroad(String broad) {
mBroad = broad;
return this;
}
public ComputerBuilder setKeyBoard(String keyBoard) {
mKeyBoard = keyBoard;
return this;
}
public ComputerBuilder setMouse(String mouse) {
mMouse = mouse;
return this;
}
public ComputerBuilder setCPU(String CPU) {
mCPU = CPU;
return this;
}
public ComputerBuilder setGPU(String GPU) {
mGPU = GPU;
return this;
}
public Computer build(){
// 可以在build方法中做一些校验等其他工作
if (mBroad.contains("技嘉")){
throw new RuntimeException("技嘉辱华,不支持技嘉主板");
}
Computer computer = new Computer(mOS,mBroad,mKeyBoard,mMouse,mCPU,mGPU);
return computer;
}
}
复制代码
旧バージョンとBuilderバージョンでオブジェクトを作成する
// 老版本的Computer对象创建
Computer computer = new Computer("MAC OS","微星 B550M","IQUNIX F97"
,"罗技 MX MASTER3","INTEL I5","NV 3060TI");
// Builder版本的Computer对象创建
Computer computer =Computer.createBuilder()
.setCPU("AMD 5600X")
.setGPU("NV 3060TI")
.setMouse("罗技 MX MASTER3")
.setKeyBoard("IQUNIX F97")
.build();
复制代码
两个版本一对比就能体现出来优势。老版本构造函数中的参数太多太长,同一个类型的参数很容易传错位,经常传参数的时候,还要看看第几个参数应该传什么。
Builder模式的对象创建,简单明了,更容易理解,而且流式的调用更加美观,不会出错。
从代码中可以看到,Computer类的构造函数是私有的,保证了所有对象的创建都必须从ComputerBuilder这个类来创建。且ComputerBuilder这个类的build方法中,可以进行校验或者其他操作。
同时,Computer这个类中是否存在Set方法,由你的实际应用场景决定,反正我的使用场景里,没有修改需求。
注意事项
- 上述代码为常见写法,并非固定模板。只要能通过Builder类创建目标对象,都可以算是建造者模式。
- 建造者模式中的目标对象的构造函数必须是private修饰。否则可以直接创建对象。Builder类就没有意义了
- 建造者模式中的目标对象是否需要Set方法,由具体需求决定。一般情况下没有Set方法,可以避免对该对象中的参数进行修改。
- Builder中的build方法,可以处理一些逻辑问题,比如校验信息等
- 工厂模式注重的是同一类型的对象中通过参数来控制具体创建哪个对象。Builder模式关注的是单一对象中的参数传递。