首页 > 解决方案 > 使用带有构建器模式的流利界面

问题描述

我试图通过创建下面的人员构建器对象来理解流利的构建器模式。我已经编写了我想使用的代码,但是在实现它时遇到了问题。我的问题如下:

  1. 调用 时HavingJob(),这应该创建一个新工作,然后可以仅使用适用于工作的方法对其进行配置,并最终添加到Jobs人员的集合中。感觉应该返回它,以便可以在其上调用其他流畅的作业方法。不确定如何实现这一点,同时允许在该级别及更高级别进行链接。
  2. 在实现这些IJobBuilder方法时,我无法访问他们在HavingJob()方法中创建的特定作业,因为我需要返回IJobBuilder以将流利的方法限制为仅与作业相关的方法。HavingJob()使这些特定作业方法可以在特定作业上运行同时仍允许链接的诀窍是什么?
  3. 一旦我走上了以 结尾的流畅路径IJobBuilder,我就不能再打电话Build()HavingJob()添加额外的工作了。这个问题的答案是有一个IJobBuilder继承自的单独实现PersonBuilder吗?
    public class Person
    {
        public string Name { get; set; }
        public List<Job> Jobs { get; set; }
        public List<Phone> Phones { get; set; }
    }

    public class Phone
    {
        public string Number { get; set; }
        public string Usage { get; set; }
    }

    public class Job
    {
        public string CompanyName { get; set; }
        public int Salary { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var p = PersonBuilder
                .Create()
                    .WithName("My Name")
                    .HavingPhone("222-222-2222")
                        .WithUsage("CELL")
                    .HavingJob()
                        .WithCompanyName("First Company")
                        .WithSalary(100)
                    .HavingJob()
                        .WithCompanyName("Second Company")
                        .WithSalary(200)
                .Build();

            Console.WriteLine(JsonConvert.SerializeObject(p));
        }
    }

    public class PersonBuilder : IJobBuilder
    {
        protected Person Person;
        public PersonBuilder() { Person = new Person(); }
        public static PersonBuilder Create() => new PersonBuilder();
        public PersonBuilder WithName(string name)
        {
            Person.Name = name;
            return this;
        }

        public PersonBuilder HavingPhone(string phoneNumber)
        {
            // Need instance of phone
            return this;
        }

        public PersonBuilder WithUsage(string phoneUsage)
        {
            // Need instance of phone
            return this;
        }

        public IJobBuilder HavingJob()
        {
            // Need to create a job here and return it so that IJobBuilder methods work on specific instance right?
            return this;
        }

        public Person Build() => Person;

        public IJobBuilder WithCompanyName(string companyName)
        {
            // How do I set the company name if I don't have the job instance here
            job.CompanyName = companyName;
            return this;
        }

        public IJobBuilder WithSalary(int amount)
        {
            // How do I set the salary if I don't have a specific job instance here
            job.Salary = amount;
            return this;
        }
    }

    public interface IJobBuilder
    {
        IJobBuilder WithCompanyName(string companyName);
        IJobBuilder WithSalary(int salary);
    }

标签: c#.net-corefluent

解决方案


单一职责原则 (SRP) 和关注点分离 (SoC)

Job Builder 应该负责构建 Job

public interface IJobBuilder {
    IJobBuilder WithCompanyName(string companyName);
    IJobBuilder WithSalary(int salary);
}

public class JobBuilder : IJobBuilder {
    private readonly Job job;

    public JobBuilder() {
        job = new Job();
    }

    public IJobBuilder WithCompanyName(string companyName) {
        job.CompanyName = companyName;
        return this;
    }

    public IJobBuilder WithSalary(int amount) {
        job.Salary = amount;
        return this;
    }

    internal Job Build() => job;
}

Person Builder 应该负责构建 Person。

public class PersonBuilder {
    protected Person Person;
    
    private PersonBuilder() { Person = new Person(); }

    public static PersonBuilder Create() => new PersonBuilder();

    public PersonBuilder WithName(string name) {
        Person.Name = name;
        return this;
    }

    public PersonBuilder HavingJob(Action<IJobBuilder> configure) {
        var builder = new JobBuilder();
        configure(builder);
        Person.Jobs.Add(builder.Build());
        return this;
    }

    public Person Build() => Person;

}

在上述构建器中,它将作业的构建委托给其负责的构建器。

这导致以下重构

class Program {
    static void Main(string[] args) {
        var p = PersonBuilder
            .Create()
                .WithName("My Name")
                .HavingJob(builder => builder
                    .WithCompanyName("First Company")
                    .WithSalary(100)
                )
                .HavingJob(builder => builder
                    .WithCompanyName("Second Company")
                    .WithSalary(200)
                )
            .Build();

        Console.WriteLine(JsonConvert.SerializeObject(p));
    }
}

推荐阅读