Accessors เป็นมากกว่าเขตข้อมูล คนอื่น ๆ ได้ชี้ให้เห็นความแตกต่างที่สำคัญหลายประการแล้วและฉันจะเพิ่มอีกหนึ่งอย่าง
คุณสมบัติมีส่วนร่วมในคลาสอินเตอร์เฟส ตัวอย่างเช่น:
interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
อินเทอร์เฟซนี้สามารถทำได้หลายวิธี ตัวอย่างเช่น:
class Person: IPerson
{
private string _name;
public string FirstName
{
get
{
return _name ?? string.Empty;
}
set
{
if (value == null)
throw new System.ArgumentNullException("value");
_name = value;
}
}
...
}
ในการใช้งานนี้เรากำลังปกป้องทั้งPerson
ชั้นเรียนจากการเข้าสู่สถานะที่ไม่ถูกต้องเช่นเดียวกับผู้โทรจากการเป็นโมฆะจากคุณสมบัติที่ไม่ได้กำหนด
แต่เราสามารถผลักดันการออกแบบให้ดียิ่งขึ้นไปอีก ตัวอย่างเช่นอินเตอร์เฟสอาจไม่จัดการกับ setter มันค่อนข้างถูกต้องตามกฎหมายที่จะกล่าวว่าผู้ใช้IPerson
อินเทอร์เฟซสนใจที่จะรับทรัพย์สินเท่านั้นไม่ใช่ในการตั้งค่า:
interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
การนำไปใช้ก่อนหน้านี้ของPerson
คลาสเป็นไปตามอินเทอร์เฟซนี้ ความจริงที่ว่ามันช่วยให้ผู้โทรยังกำหนดคุณสมบัติที่ไม่มีความหมายจากมุมมองของผู้บริโภค (ที่กินIPerson
) ฟังก์ชั่นเพิ่มเติมของการใช้งานที่เป็นรูปธรรมนั้นถูกนำมาพิจารณาด้วยเช่นการสร้าง:
class PersonBuilder: IPersonBuilder
{
IPerson BuildPerson(IContext context)
{
Person person = new Person();
person.FirstName = context.GetFirstName();
person.LastName = context.GetLastName();
return person;
}
}
...
void Consumer(IPersonBuilder builder, IContext context)
{
IPerson person = builder.BuildPerson(context);
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
ในรหัสนี้ผู้บริโภคไม่ทราบเกี่ยวกับผู้ตั้งทรัพย์สิน - ไม่ใช่ธุรกิจของเขาที่จะรู้เกี่ยวกับมัน ผู้บริโภคต้องการเพียงแค่ getters และเขาได้รับ getters จากอินเทอร์เฟซคือจากสัญญา
การดำเนินการที่ถูกต้องสมบูรณ์อีกอย่างหนึ่งคือIPerson
คลาสบุคคลที่ไม่เปลี่ยนรูปและโรงงานบุคคลที่เกี่ยวข้อง:
class Person: IPerson
{
public Person(string firstName, string lastName)
{
if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
throw new System.ArgumentException();
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
}
...
class PersonFactory: IPersonFactory
{
public IPerson CreatePerson(string firstName, string lastName)
{
return new Person(firstName, lastName);
}
}
...
void Consumer(IPersonFactory factory)
{
IPerson person = factory.CreatePerson("John", "Doe");
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
ในผู้บริโภคตัวอย่างรหัสนี้อีกครั้งไม่มีความรู้ในการเติมคุณสมบัติ ผู้บริโภคเท่านั้นที่เกี่ยวข้องกับ getters และการใช้งานที่เป็นรูปธรรม (และตรรกะทางธุรกิจที่อยู่เบื้องหลังมันเช่นการทดสอบว่าชื่อว่างเปล่า) จะถูกทิ้งให้อยู่ในชั้นเรียนพิเศษ - ผู้สร้างและโรงงาน การดำเนินการทั้งหมดเหล่านี้เป็นไปไม่ได้อย่างเต็มที่กับเขตข้อมูล