7.建造者模式

7,创建型模式-建造者模式


7.1 基础知识

学习难度:4

使用频率:2

总分:4

定义

建造者模式(Builder Pattern)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

说人话

建造者拆分建造产品的过程,指挥者指挥建造者如何建造,最终得到产品对象。

结构图

实现步骤

  • 产品类:定义产品属性和展示产品方法
  • 建造者接口:定义建造产品属性方法和返回产品方法
  • 具体建造者类:实现建造者接口,定义实例化的私有产品对象
  • 指挥者类:定义建造者对象在构造函数传入初始化,定义构建产品方法,指挥建造者对象如何建造产品属性
  • 客户端:创建具体建造者,创建指挥者传入具体建造者,指挥者构建的产品,具体建造者得到产品,展示产品

说明

建造者模式常用于构建复杂对象,当一个对象的构建过程比较复杂,而且对象的各个部分之间存在着复杂的构建顺序或依赖关系时,可以考虑使用建造者模式。通过建造者模式,可以将构建过程分解成多个简单的步骤,使得构建过程更加灵活,同时也易于扩展和维护。


7.2 模版代码

产品类

// 产品类
class Product
{
    public string Part1 { get; set; }
    public string Part2 { get; set; }

    public void Show()
    {
        Console.WriteLine($"展示产品 Part1: {Part1}, Part2: {Part2}");
    }
}

建造者接口和具体建造者

// 建造者接口
interface IBuilder
{
    void BuildPart1();
    void BuildPart2();
    Product GetResult();
}

// 具体建造者类
class ConcreteBuilder : IBuilder
{
    private Product product = new Product();

    public void BuildPart1()
    {
        product.Part1 = "我是ConcreteBuilder创建的Part1";
    }

    public void BuildPart2()
    {
        product.Part2 = "我是ConcreteBuilder创建的Part2";
    }

    public Product GetResult()
    {
        return product;
    }
}

指挥官

// 指挥者类
class Director
{
    private IBuilder builder;

    public Director(IBuilder builder)
    {
        this.builder = builder;
    }

    public void Construct()
    {
        builder.BuildPart1();
        builder.BuildPart2();
    }
}

客户端

class Program
{
    static void Main(string[] args)
    {
        // 创建具体建造者
        IBuilder builder = new ConcreteBuilder();
        
        // 创建指挥官传入具体建造者
        Director director = new Director(builder);

        // 指挥官构建的产品
        director.Construct();
        
        // 具体建造者得到产品
        Product product = builder.GetResult();

        // 展示产品 
        product.Show();//展示产品 Part1: 我是ConcreteBuilder创建的Part1, Part2: 我是ConcreteBuilder创建的Part2
    }
}

7.3 CSharp实践

实践需求

使用建造者模式建造宝马和奔驰的车,要求要构建发动机,轮子,车身

车产品类

//车产品类
public class CarProduct
{
    //汽车的各个部件,可以是任意类型
    public string Engine { get; set; } //发动机
    public string Wheel { get; set; } //轮子
    public string Body { get; set; } //车身

    //启动汽车
    public void RunCar()
    {
        Console.WriteLine("汽车启动,发动机是{0},轮子是{1},车身是{2}", Engine, Wheel, Body);
    }
}

车建造者接口和具体车建造者类

//车建造者接口
public interface ICarBuilder
{
    //创建发动机的抽象方法
    public abstract void BuildEngine();

    //创建轮子的抽象方法
    public abstract void BuildWheel();

    //创建车身的抽象方法
    public abstract void BuildBody();

    //获取产品的抽象方法
    public abstract CarProduct GetCarProduct();
}

//奔驰车建造者类
class BenzCarBuilder : ICarBuilder
{
    //创建一个空的汽车对象
    private CarProduct carProduct = new CarProduct();

    //重写创建发动机的方法,设置汽车对象的发动机属性为奔驰发动机
    public void BuildEngine()
    {
        carProduct.Engine = "奔驰发动机";
    }

    //重写创建轮子的方法,设置汽车对象的轮子属性为奔驰轮子
    public void BuildWheel()
    {
        carProduct.Wheel = "奔驰轮子";
    }

    //重写创建车身的方法,设置汽车对象的车身属性为奔驰车身
    public void BuildBody()
    {
        carProduct.Body = "奔驰车身";
    }

    //重写获取产品的方法,返回构建好的汽车对象
    public CarProduct GetCarProduct()
    {
        return carProduct;
    }
}

//宝马车建造者
class BMWCarBuilder : ICarBuilder
{
    //创建一个空的汽车对象
    private CarProduct carProduct = new CarProduct();

    //重写创建发动机的方法,设置汽车对象的发动机属性为宝马发动机
    public void BuildEngine()
    {
        carProduct.Engine = "宝马发动机";
    }

    //重写创建轮子的方法,设置汽车对象的轮子属性为宝马轮子
    public void BuildWheel()
    {
        carProduct.Wheel = "宝马轮子";
    }

    //重写创建车身的方法,设置汽车对象的车身属性为宝马车身
    public void BuildBody()
    {
        carProduct.Body = "宝马车身";
    }

    //重写获取产品的方法,返回构建好的汽车对象
    public CarProduct GetCarProduct()
    {
        return carProduct;
    }
}

车指挥官类

//指挥者官,包含一个抽象建造者类型的属性和一个构建产品的方法
class CarDirector
{
    //抽象建造者类型的属性,用来接收具体建造者对象
    private ICarBuilder builder;

    //构造函数,用来初始化抽象建造者属性
    public CarDirector(ICarBuilder builder)
    {
        this.builder = builder;
    }

    //构建产品的方法,可以指定创建产品的各个部件的顺序和逻辑
    public void Construct()
    {
        //先创建发动机
        builder.BuildEngine();
        //再创建轮子
        builder.BuildWheel();
        //最后创建车身
        builder.BuildBody();
    }
}

客户端

class Program
{
    static void Main(string[] args)
    {
        ICarBuilder benzBuilder = new BenzCarBuilder();
        CarDirector director = new CarDirector(benzBuilder);
        director.Construct();
        CarProduct benzCarProduct = benzBuilder.GetCarProduct();
        benzCarProduct.RunCar();//汽车启动,发动机是奔驰发动机,轮子是奔驰轮子,车身是奔驰车身
        
        ICarBuilder bmwBuilder = new BMWCarBuilder();
        CarDirector bmwDirector = new CarDirector(bmwBuilder);
        bmwDirector.Construct();
        CarProduct bmwCarProduct = bmwBuilder.GetCarProduct();
        bmwCarProduct.RunCar();//汽车启动,发动机是宝马发动机,轮子是宝马轮子,车身是宝马车身
    }
}

7.4 Unity实践

实践需求

使用建造者模式,建造暗夜猎手薇恩和无极剑圣易,建造时要传入名字和英雄位置分类

英雄产品类

public class HeroProduct
{
    public string name;
    public string roleLane;
    public const string PrefabConstPath = "Lesson08_创建型模式_建造者模式";

    public void CreateHeroPrefab()
    {
        Debug.Log($"创建英雄,英雄名字是{name},位置是{roleLane}");
        GameObject prefab = Resources.Load<GameObject>(PrefabConstPath +"/" +name);
        GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity);
    }
}

英雄建造者接口和具体英雄建造者类

public interface IHeroBuilder
{
    void SetName();
    void SetRoleLane();
    HeroProduct ReturnHeroProduct();
}

public class VayneBuilder:IHeroBuilder
{
    private readonly HeroProduct heroProduct = new HeroProduct();
    
    public  void SetName()
    {
        heroProduct.name = "Vayne";
    }

    public  void SetRoleLane()
    {
        heroProduct.roleLane = "ADC";
    }

    public  HeroProduct ReturnHeroProduct()
    {
        return heroProduct;
    }
}

public class YiBuilder:IHeroBuilder
{
    private readonly HeroProduct heroProduct = new HeroProduct();
    
    public  void SetName()
    {
        heroProduct.name = "Yi";
    }

    public  void SetRoleLane()
    {
        heroProduct.roleLane = "Jungle";
    }

    public  HeroProduct ReturnHeroProduct()
    {
        return heroProduct;
    }
}

英雄指挥官

public class HeroDirector
{
    private IHeroBuilder heroBuilder;

    public HeroDirector(IHeroBuilder heroBuilder)
    {
        this.heroBuilder = heroBuilder;
    }

    public void Construct()
    {
        heroBuilder.SetName();
        heroBuilder.SetRoleLane();
    }
}

客户端

public class TestBuilderPattern : MonoBehaviour
{
    void Start()
    {
        IHeroBuilder vayneBuilder = new VayneBuilder();
        IHeroBuilder yiBuilder = new YiBuilder();
    
        ShowHero(vayneBuilder);
        ShowHero(yiBuilder);
    }

    public void ShowHero(IHeroBuilder heroBuilder)
    {
        HeroDirector heroDirector = new HeroDirector(heroBuilder);
        heroDirector.Construct();
    
        HeroProduct heroProduct  = heroBuilder.ReturnHeroProduct();
        heroProduct.CreateHeroPrefab();
    }
}

运行结果



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏