我正在尝试创建一个构建一个Person对象实例的构建器类。问题是它创建了三个Person对象。我知道这一点,因为它触发构造函数三次(它向控制台写入三次)。我该怎么做才能创造一个呢?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
namespace DotNetDesignPatternDemos.Creational.BuilderFacets
{
public class Person
{
// address
public string StreetAddress, Postcode, City;
// employment
public string CompanyName, Position;
public int AnnualIncome;
public Person()
{
Console.WriteLine("Person instanced");
}
public override string ToString()
{
return $"{nameof(StreetAddress)}: {StreetAddress}, {nameof(Postcode)}: {Postcode}, {nameof(City)}: {City}, {nameof(CompanyName)}: {CompanyName}, {nameof(Position)}: {Position}, {nameof(AnnualIncome)}: {AnnualIncome}";
}
}
public class PersonBuilder
{
protected Person person = new Person();
public PersonAddressBuilder Lives => new PersonAddressBuilder(person);
public PersonJobBuilder Works => new PersonJobBuilder(person);
public Person Build()
{
return this.person;
}
}
public class PersonJobBuilder : PersonBuilder
{
public PersonJobBuilder(Person person)
{
this.person = person;
}
public PersonJobBuilder At(string companyName)
{
person.CompanyName = companyName;
return this;
}
public PersonJobBuilder AsA(string position)
{
person.Position = position;
return this;
}
public PersonJobBuilder Earning(int annualIncome)
{
person.AnnualIncome = annualIncome;
return this;
}
}
public class PersonAddressBuilder : PersonBuilder
{
public PersonAddressBuilder(Person person)
{
this.person = person;
}
public PersonAddressBuilder At(string streetAddress)
{
person.StreetAddress = streetAddress;
return this;
}
public PersonAddressBuilder WithPostcode(string postcode)
{
person.Postcode = postcode;
return this;
}
public PersonAddressBuilder In(string city)
{
person.City = city;
return this;
}
}
public class Demo
{
static void Main(string[] args)
{
var pb = new PersonBuilder();
Person person = pb
.Lives
.At("123 London Road")
.In("London")
.WithPostcode("SW12BC")
.Works
.At("Fabrikam")
.AsA("Engineer")
.Earning(123000).Build();
WriteLine(person);
}
}
}
结果是
Person instanced
Person instanced
Person instanced
StreetAddress: 123 London Road, Postcode: SW12BC, City: London, CompanyName: Fab
rikam, Position: Engineer, AnnualIncome: 123000
基本上,它需要为每个Builder实例创建一个Person实例。
我不认为Singleton是解决方案,因为我不需要全局可访问的对象。
每个衍生的建造者都继承自PersonBuilder
,所以当你新建一个PersonJobBuilder
时,你也是新来的Person
var pb = new PersonBuilder();
public PersonAddressBuilder Lives => new PersonAddressBuilder(person);
public PersonJobBuilder Works => new PersonJobBuilder(person);
因此,每个新的一个Person
,三个实例。
编辑
快速解决方法是让你的Person
实例静态,只有一个存在。从技术上讲,你的教程代码确实有用,它不能保证创建一个人对象,但你总是对当前人进行操作。
public class Person
{
// address
public string StreetAddress, Postcode, City;
// employment
public string CompanyName, Position;
public int AnnualIncome;
public Person()
{
Console.WriteLine("Person instanced");
}
public override string ToString()
{
return $"{nameof(StreetAddress)}: {StreetAddress}, {nameof(Postcode)}: {Postcode}, {nameof(City)}: {City}, {nameof(CompanyName)}: {CompanyName}, {nameof(Position)}: {Position}, {nameof(AnnualIncome)}: {AnnualIncome}";
}
}
public class PersonBuilder
{
protected static Person _person = new Person();
public PersonAddressBuilder Lives => new PersonAddressBuilder(_person);
public PersonJobBuilder Works => new PersonJobBuilder(_person);
public Person Build()
{
return _person;
}
}
public class PersonJobBuilder : PersonBuilder
{
public PersonJobBuilder(Person person)
{
_person = person;
}
public PersonJobBuilder At(string companyName)
{
_person.CompanyName = companyName;
return this;
}
public PersonJobBuilder AsA(string position)
{
_person.Position = position;
return this;
}
public PersonJobBuilder Earning(int annualIncome)
{
_person.AnnualIncome = annualIncome;
return this;
}
}
public class PersonAddressBuilder : PersonBuilder
{
public PersonAddressBuilder(Person person)
{
_person = person;
}
public PersonAddressBuilder At(string streetAddress)
{
_person.StreetAddress = streetAddress;
return this;
}
public PersonAddressBuilder WithPostcode(string postcode)
{
_person.Postcode = postcode;
return this;
}
public PersonAddressBuilder In(string city)
{
_person.City = city;
return this;
}
}
public class Demo
{
static void Main(string[] args)
{
var pb = new PersonBuilder();
Person person = pb
.Lives
.At("123 London Road")
.In("London")
.WithPostcode("SW12BC")
.Works
.At("Fabrikam")
.AsA("Engineer")
.Earning(123000).Build();
WriteLine(person);
Console.ReadLine();
}
}