定义
建造者模式是一种创建型设计模式,它允许你逐步构建复杂对象,而无需使用多个构造函数或重载。建造者模式将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。
正确写法
假设我们有一个复杂的 Car 对象,需要逐步构建其各个部分(如引擎、轮胎、颜色等)。
// 产品类
public class Car
{public string Engine { get; set; }public string Tires { get; set; }public string Color { get; set; }public override string ToString(){return $"Car: Engine={Engine}, Tires={Tires}, Color={Color}";}
}// 抽象建造者
public abstract class CarBuilder
{protected Car car;public Car GetCar() => car;public abstract void BuildEngine();public abstract void BuildTires();public abstract void BuildColor();
}// 具体建造者
public class SportsCarBuilder : CarBuilder
{public SportsCarBuilder(){car = new Car();}public override void BuildEngine() => car.Engine = "V8";public override void BuildTires() => car.Tires = "High-performance tires";public override void BuildColor() => car.Color = "Red";
}public class LuxuryCarBuilder : CarBuilder
{public LuxuryCarBuilder(){car = new Car();}public override void BuildEngine() => car.Engine = "V6";public override void BuildTires() => car.Tires = "All-season tires";public override void BuildColor() => car.Color = "Black";
}// 导演类
public class Director
{public void Construct(CarBuilder builder){builder.BuildEngine();builder.BuildTires();builder.BuildColor();}
}// 客户端代码
class Program
{static void Main(string[] args){Director director = new Director();CarBuilder sportsCarBuilder = new SportsCarBuilder();director.Construct(sportsCarBuilder);Car sportsCar = sportsCarBuilder.GetCar();Console.WriteLine(sportsCar);CarBuilder luxuryCarBuilder = new LuxuryCarBuilder();director.Construct(luxuryCarBuilder);Car luxuryCar = luxuryCarBuilder.GetCar();Console.WriteLine(luxuryCar);}
}
类图:
解释
- 产品类 (Car):定义了汽车的属性(引擎、轮胎、颜色)和一个重写的 ToString 方法,用于显示汽车的详细信息。
- 抽象建造者 (
CarBuilder
):定义了一个受保护的Car
对象,并提供了获取汽车的方法GetCar
以及三个抽象方法BuildEngine
、BuildTires
和BuildColor
。 - 具体建造者 (
SportsCarBuilder
和LuxuryCarBuilder
):继承自CarBuilder
,具体实现了构建汽车各个部分的方法。 - 导演类 (
Director
):负责调用具体建造者的构建方法,按照一定的顺序构建汽车。 - 客户端代码 (
Program
):创建了Director
对象和具体的建造者对象,通过导演类的Construct
方法构建汽车,并最终获取和显示汽车的信息。
用途
- 逐步构建复杂对象:当对象的构建过程复杂且需要多个步骤时,使用建造者模式可以将构建过程分解为多个方法调用。
- 分离构建过程和表示:建造者模式将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。
- 避免大量的构造函数:避免使用多个构造函数或重载,使代码更加清晰和易于维护。
优点
- 封装性好:将对象的构建过程封装在建造者类中,客户端代码不需要关心具体的构建细节。
- 代码复用性高:相同的构建过程可以创建不同的表示,提高了代码的复用性。
- 易于扩展:增加新的建造者类时,不需要修改现有的代码,符合开闭原则。
缺点
- 代码复杂度增加:引入了多个类(抽象建造者、具体建造者、导演类等),系统结构变得更复杂。
- 增加类的数量:每增加一个新的产品类型,就需要增加相应的建造者类,类的数量会增加。
- 灵活性受限:如果产品的内部表示发生变化,可能需要修改多个建造者类。
适用场景 - 对象构建过程复杂:当对象的构建过程复杂且需要多个步骤时。
- 对象的表示多种多样:当需要创建多种不同表示的对象时。
- 避免大量的构造函数:当对象的构造函数参数较多且复杂时。
实际开发中的应用
1. 配置文件解析
假设我们需要解析一个复杂的配置文件,并根据配置文件的内容创建相应的对象。
代码如下:
// 配置对象
public class Configuration
{public string Host { get; set; }public int Port { get; set; }public string Username { get; set; }public string Password { get; set; }public override string ToString(){return $"Configuration: Host={Host}, Port={Port}, Username={Username}, Password={Password}";}
}// 抽象建造者
public abstract class ConfigurationBuilder
{protected Configuration configuration;public Configuration GetConfiguration() => configuration;public abstract void BuildHost();public abstract void BuildPort();public abstract void BuildUsername();public abstract void BuildPassword();
}// 具体建造者
public class ProductionConfigBuilder : ConfigurationBuilder
{public ProductionConfigBuilder(){configuration = new Configuration();}public override void BuildHost() => configuration.Host = "prod.example.com";public override void BuildPort() => configuration.Port = 8080;public override void BuildUsername() => configuration.Username = "admin";public override void BuildPassword() => configuration.Password = "securepassword";
}public class DevelopmentConfigBuilder : ConfigurationBuilder
{public DevelopmentConfigBuilder(){configuration = new Configuration();}public override void BuildHost() => configuration.Host = "dev.example.com";public override void BuildPort() => configuration.Port = 8081;public override void BuildUsername() => configuration.Username = "devuser";public override void BuildPassword() => configuration.Password = "devpassword";
}// 导演类
public class ConfigDirector
{public void Construct(ConfigurationBuilder builder){builder.BuildHost();builder.BuildPort();builder.BuildUsername();builder.BuildPassword();}
}// 客户端代码
class Program
{static void Main(string[] args){ConfigDirector director = new ConfigDirector();ConfigurationBuilder productionBuilder = new ProductionConfigBuilder();director.Construct(productionBuilder);Configuration productionConfig = productionBuilder.GetConfiguration();Console.WriteLine(productionConfig);ConfigurationBuilder developmentBuilder = new DevelopmentConfigBuilder();director.Construct(developmentBuilder);Configuration developmentConfig = developmentBuilder.GetConfiguration();Console.WriteLine(developmentConfig);}
}
2. 报告生成
假设我们需要生成不同类型的报告(如 PDF 报告和 HTML 报告),并逐步构建报告的内容。
// 报告对象
public class Report
{public string Title { get; set; }public string Content { get; set; }public string Footer { get; set; }public override string ToString(){return $"Report: Title={Title}, Content={Content}, Footer={Footer}";}
}// 抽象建造者
public abstract class ReportBuilder
{protected Report report;public Report GetReport() => report;public abstract void BuildTitle();public abstract void BuildContent();public abstract void BuildFooter();
}// 具体建造者
public class PdfReportBuilder : ReportBuilder
{public PdfReportBuilder(){report = new Report();}public override void BuildTitle() => report.Title = "PDF Report Title";public override void BuildContent() => report.Content = "This is the content of the PDF report.";public override void BuildFooter() => report.Footer = "Generated by PDF Report Builder";
}public class HtmlReportBuilder : ReportBuilder
{public HtmlReportBuilder(){report = new Report();}public override void BuildTitle() => report.Title = "HTML Report Title";public override void BuildContent() => report.Content = "This is the content of the HTML report.";public override void BuildFooter() => report.Footer = "Generated by HTML Report Builder";
}// 导演类
public class ReportDirector
{public void Construct(ReportBuilder builder){builder.BuildTitle();builder.BuildContent();builder.BuildFooter();}
}// 客户端代码
class Program
{static void Main(string[] args){ReportDirector director = new ReportDirector();ReportBuilder pdfBuilder = new PdfReportBuilder();director.Construct(pdfBuilder);Report pdfReport = pdfBuilder.GetReport();Console.WriteLine(pdfReport);ReportBuilder htmlBuilder = new HtmlReportBuilder();director.Construct(htmlBuilder);Report htmlReport = htmlBuilder.GetReport();Console.WriteLine(htmlReport);}
}
总结
建造者模式 通过将对象的构建过程分解为多个方法调用,使得对象的创建更加灵活和可控。虽然它增加了系统的复杂度,但在需要逐步构建复杂对象的场景中,建造者模式能够显著提高代码的可维护性和扩展性。
在我看来,切碎一点,繁琐一点,微操大神,优势在我