使用带有构建器模式的流畅界面 [英] Using fluent interface with builder pattern

查看:23
本文介绍了使用带有构建器模式的流畅界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to understand fluent builder pattern by creating the person builder object below. I've written the code as I would like to use it but am having issues with implementing it. My issues are as follows:

  1. 当调用 HavingJob() 时,这应该创建一个新作业,然后可以仅使用适用于作业的方法进行配置,并最终添加到 Jobs 集合中人.感觉应该返回它,以便可以在其上调用其他流畅的作业方法.不确定如何实现这一点,同时允许在该级别及更高级别进行链接.
  2. 在实现 IJobBuilder 方法时,我无法访问他们在 HavingJob() 方法中创建的特定作业,因为我需要返回 IJobBuilder 将 fluent 方法限制为仅与作业相关的方法.HavingJob() 的技巧是什么,以便那些特定的作业方法可以对特定作业进行操作,同时仍然允许链接?
  3. 一旦我走上了以 IJobBuilder 结尾的流畅路径,我就不能再调用 Build()HavingJob() 来添加额外的工作.对此的答案是否是从 PersonBuilder 继承的 IJobBuilder 的单独实现?
  1. When calling HavingJob(), this should create a new job that can then be configured using only applicable methods for a job and ultimately added to the Jobs collection of the person. It feels like should return it so that other fluent job methods can be called on it. Not sure how to implement that awhile allowing chaining at that level and above.
  2. When implementing the IJobBuilder methods, I don't have access to the specific job they created in the HavingJob() method because I need to return the IJobBuilder to restrict the fluent methods to only be the ones related to the job. What is the trick to HavingJob() so that those specific job methods can operate on a specific job while still allowing for chaining?
  3. Once I go down a fluent path that ends with IJobBuilder, I can no longer call Build() or HavingJob() to add additional jobs. Would the answer to that one be to have a separate implementation of IJobBuilder that inherits from 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);
    }

推荐答案

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

Job Builder 应该负责构建 Job

Single Responsibility Principle (SRP) and Separation of Concerns (SoC)

A Job Builder should be responsible for building a 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.

A Person Builder should be responsible for building the 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;

}

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

In the above builder it delegates the building of the job to its responsible builder.

这导致以下重构

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));
    }
}

这篇关于使用带有构建器模式的流畅界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆