建造者模式
约 636 字
建造者模式
核心思想
建造者模式允许逐步构建复杂对象。
典型用例
文本构建
在需要动态构建复杂的SQL查询或其他任何形式的文本时,可以使用建造者模式来逐步构建文本的不同部分。
在这个例子中,建造者的实现类提供了一系列方法来构建 SQL 查询的不同部分。这些方法返回建造者对象本身,从而允许链式调用。通过这种方式,你可以清晰且灵活地构建出复杂的 SQL 查询或其他形式的文本。这种模式特别适用于构建那些根据不同条件和上下文变化的复杂对象。
// npm run code src/code/design-pattern/builder/text-construction.ts
export {};
// 定义一个建造者接口,这个接口将规定必须实现哪些方法来构建 SQL 查询的不同部分
interface SQLQueryBuilder {
select(table: string, fields: string[]): SQLQueryBuilder;
where(conditions: string): SQLQueryBuilder;
orderBy(field: string, direction: 'ASC' | 'DESC'): SQLQueryBuilder;
getQuery(): string;
}
// 具体建造者
class SQLQuery implements SQLQueryBuilder {
private query: string = '';
select(table: string, fields: string[]): SQLQueryBuilder {
this.query += `SELECT ${fields.join(', ')} FROM ${table}`;
return this;
}
where(conditions: string): SQLQueryBuilder {
this.query += ` WHERE ${conditions}`;
return this;
}
orderBy(field: string, direction: 'ASC' | 'DESC'): SQLQueryBuilder {
this.query += ` ORDER BY ${field} ${direction}`;
return this;
}
getQuery(): string {
return this.query;
}
}
const queryBuilder = new SQLQuery();
const query = queryBuilder
.select("users", ["name", "age", "email"])
.where("age > 18")
.orderBy("name", "ASC")
.getQuery();
// 输出: SELECT name, age, email FROM users WHERE age > 18 ORDER BY name ASC
console.log(query);
构建复杂对象
建造者模式是一种用于创建复杂对象的设计模式,它允许你将一个复杂对象的构造过程分解成更小的、更易管理的部分。这种模式在处理需要多个步骤来构造的对象时非常有用。
// npm run code src/code/design-pattern/builder/building-complex-objects.ts
export {};
// 产品类
class MyDocument {
private parts: string[] = [];
addPart(part: string): void {
this.parts.push(part);
}
show(): void {
console.log("Document Parts: ", this.parts.join(", "));
}
}
// 建造者接口
interface DocumentBuilder {
buildHeader(): void;
buildBody(): void;
buildFooter(): void;
getDocument(): MyDocument;
}
// 具体建造者
class MyDocumentBuilder implements DocumentBuilder {
private document: MyDocument = new MyDocument();
buildHeader(): void {
this.document.addPart("Header");
}
buildBody(): void {
this.document.addPart("Body");
}
buildFooter(): void {
this.document.addPart("Footer");
}
getDocument(): MyDocument {
return this.document;
}
}
// 指挥者
class Director {
construct(builder: DocumentBuilder): void {
builder.buildHeader();
builder.buildBody();
builder.buildFooter();
}
}
// 使用
const director = new Director();
const builder = new MyDocumentBuilder();
director.construct(builder);
const doc = builder.getDocument();
doc.show();
处理可选参数
建造者模式适合处理具有多个可选参数的对象,这种模式允许逐步构建对象,而不是通过一个包含许多参数的构造函数,这样不仅使代码更易读和维护,还可以避免创建包含多个参数的复杂构造函数,特别是当很多参数是可选的时候。
// npm run code src/code/design-pattern/builder/process-optional-parameters.ts
export {};
// 产品类
class Product {
private name?: string;
private price?: number;
private description?: string;
private category?: string;
setName(name: string): void {
this.name = name;
}
setPrice(price: number): void {
this.price = price;
}
setDescription(description: string): void {
this.description = description;
}
setCategory(category: string): void {
this.category = category;
}
getDescription(): string {
return `
Product: ${this.name}, Price: ${this.price},
Description: ${this.description}, Category: ${this.category}
`;
}
}
// 建造者类
class ProductBuilder {
private product: Product = new Product();
setName(name: string): ProductBuilder {
this.product.setName(name);
return this;
}
setPrice(price: number): ProductBuilder {
this.product.setPrice(price);
return this;
}
setDescription(description: string): ProductBuilder {
this.product.setDescription(description);
return this;
}
setCategory(category: string): ProductBuilder {
this.product.setCategory(category);
return this;
}
build(): Product {
return this.product;
}
}
// 使用建造者
const productBuilder = new ProductBuilder();
const product = productBuilder
.setName("Awesome Product")
.setPrice(19.99)
.setDescription("This is a great product")
.build();
console.log(product.getDescription());
构建不同表现形式对象
建造者模式可以通过定义多个具体建造者来实现在相同的构建过程中创建具有不同表示或配置的对象,每个具体建造者负责构建具有特定属性和特征的对象。这种方式非常适合创建如汽车模型这样的复杂对象,其中每个模型可能有不同的配置和特性。
// npm run code src/code/design-pattern/builder/building-variations-objects.ts
export {};
// 产品类
class Car {
public parts: string[] = [];
addPart(part: string): void {
this.parts.push(part);
}
listParts(): void {
console.log(`Car parts: ${this.parts.join(', ')}\n`);
}
}
// 建造者接口
interface CarBuilder {
reset(): void;
setSeats(number: number): void;
setEngine(engine: string): void;
setTripComputer(hasComputer: boolean): void;
setGPS(hasGPS: boolean): void;
getResult(): Car;
}
// 运动型汽车建造者
class SportsCarBuilder implements CarBuilder {
private car = new Car();
reset(): void {
this.car = new Car();
}
setSeats(number: number): void {
this.car.addPart(`${number} seats`);
}
setEngine(engine: string): void {
this.car.addPart(`Engine: ${engine}`);
}
setTripComputer(hasComputer: boolean): void {
if (hasComputer) {
this.car.addPart("Trip Computer");
}
}
setGPS(hasGPS: boolean): void {
if (hasGPS) {
this.car.addPart("GPS");
}
}
getResult(): Car {
return this.car;
}
}
// 家用汽车建造者
class FamilyCarBuilder implements CarBuilder {
private car = new Car();
reset(): void {
this.car = new Car();
}
setSeats(number: number): void {
this.car.addPart(`${number} seats`);
}
setEngine(engine: string): void {
this.car.addPart(`Engine: ${engine}`);
}
setTripComputer(hasComputer: boolean): void {
if (hasComputer) {
this.car.addPart("Trip Computer");
}
}
setGPS(hasGPS: boolean): void {
if (hasGPS) {
this.car.addPart("GPS");
}
}
getResult(): Car {
return this.car;
}
}
// 指挥者
class Director {
constructSportsCar(builder: CarBuilder): void {
builder.reset();
builder.setSeats(2);
builder.setEngine("V8");
builder.setTripComputer(true);
builder.setGPS(true);
}
constructFamilyCar(builder: CarBuilder): void {
builder.reset();
builder.setSeats(5);
builder.setEngine("V6");
builder.setTripComputer(false);
builder.setGPS(true);
}
}
// 使用
const director = new Director();
const sportsCarBuilder = new SportsCarBuilder();
director.constructSportsCar(sportsCarBuilder);
const sportsCar = sportsCarBuilder.getResult();
sportsCar.listParts();
const familyCarBuilder = new FamilyCarBuilder();
director.constructFamilyCar(familyCarBuilder);
const familyCar = familyCarBuilder.getResult();
familyCar.listParts();
构建初始过程复杂对象
它允许将一个复杂的创建过程分解成多个较小的、易于管理的部分。这种方式使得代码更加清晰和易于理解,特别是当对象构建需要多个步骤或配置时。
// npm run code src/code/design-pattern/builder/building-initial-complex-objects.ts
// 产品类
class Computer {
private cpu?: string;
private ram?: number;
private ssd?: number;
private gpu?: string;
setCPU(cpu: string): void {
this.cpu = cpu;
}
setRAM(ram: number): void {
this.ram = ram;
}
setSSD(ssd: number): void {
this.ssd = ssd;
}
setGPU(gpu: string): void {
this.gpu = gpu;
}
getSpecifications(): string {
return `Computer Specifications: CPU = ${this.cpu}, RAM = ${this.ram}GB, SSD = ${this.ssd}GB, GPU = ${this.gpu}`;
}
}
// 建造者接口
interface ComputerBuilder {
setCPU(cpu: string): ComputerBuilder;
setRAM(ram: number): ComputerBuilder;
setSSD(ssd: number): ComputerBuilder;
setGPU(gpu: string): ComputerBuilder;
build(): Computer;
}
// 具体建造者
class MyComputerBuilder implements ComputerBuilder {
private computer: Computer = new Computer();
setCPU(cpu: string): ComputerBuilder {
this.computer.setCPU(cpu);
return this;
}
setRAM(ram: number): ComputerBuilder {
this.computer.setRAM(ram);
return this;
}
setSSD(ssd: number): ComputerBuilder {
this.computer.setSSD(ssd);
return this;
}
setGPU(gpu: string): ComputerBuilder {
this.computer.setGPU(gpu);
return this;
}
build(): Computer {
return this.computer;
}
}
// 使用建造者
const builder = new MyComputerBuilder();
const computer = builder
.setCPU("Intel Core i7")
.setRAM(16)
.setSSD(512)
.setGPU("NVIDIA RTX 3080")
.build();
console.log(computer.getSpecifications());