使用带有构建器模式的流畅界面

Gee*_*ekn 3 c# fluent .net-core

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

  1. 调用 时HavingJob(),这应该创建一个新作业,然后可以仅使用适用于作业的方法进行配置,并最终添加到Jobs人员集合中。感觉应该返回它,以便可以在其上调用其他流畅的作业方法。不确定如何实现这一点,同时允许在该级别及更高级别进行链接。
  2. 在实现这些IJobBuilder方法时,我无法访问他们在HavingJob()方法中创建的特定作业,因为我需要返回IJobBuilder以将 fluent 方法限制为仅与作业相关的方法。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);
    }
Run Code Online (Sandbox Code Playgroud)

Nko*_*osi 13

单一职责原则 (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;
}
Run Code Online (Sandbox Code Playgroud)

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;

}
Run Code Online (Sandbox Code Playgroud)

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

这导致以下重构

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));
    }
}
Run Code Online (Sandbox Code Playgroud)