Table of Contents
הבנת התבנית המעניינת לבניית אובייקטים מורכבים ב-C#
בניית אובייקטים מורכבים ב C# לעתים קרובות מוביל לבונים עם רשימות פרמטר ארוכות, לוגיקה ראשונית מסובבת, וקוד שקשה לקרוא או לשמור עליו.TheFLT:0Builder PatternofLT:1 מציע פתרון נקי על ידי הפרדת הבנייה של אובייקט מורכב מייצוגו.תבנית עיצוב זו מאפשרת לך לייצר תצורה שונה של אובייקט באמצעות תהליך בנייה זהה, מה שהופך את הקוד שלך גמיש יותר וליצור אובייקטים קלים יותר.
בין אם אתה מחלחל אובייקט תצורה עם עשרות תכונות אופציונליות, בניית דו"ח מורכב, או הקמת צינור נתונים מתוחכם, תבנית הרוכש מספקת גישה מובנית, צעד אחר צעד. במאמר זה אנו נבחן את התבנית לעומק: מרכיבי הליבה שלה, דוגמאות C# מעשי, וריאציות כמו בונה שוטפת, וכאשר לבחור אותה על פני דפוסים אחרים הבריאה עד הסוף אתה מוכן ליישם את התבנית שלך כדי יצירת תבנית.
מהו תבנית ה-Neative?
התבנית המארגנת היא תבנית עיצובית של ההרחבה:0 בילויית של עיצוב עיצוב איור 1 (FLT:0) אשר מקלקלת את בנייתו של חפץ מורכב מהייצוג הסופי שלו, במקום לכפות על לקוח להעביר כל פרמטר למבנה יחיד, התבנית מאפשרת לך לבנות את היצירה האובייקט על ידי פיסת פיסת נייר, לעתים קרובות באמצעות סדרה של שיחות שיטה.ה אותו בונה ניתן להזמין על ידי מנהל כדי ליצור ייצוגים שונים (למשל, "בית סטנדרטי" לעומת "מות" (למשל," בית סטנדרטי).
התבנית מועילה במיוחד כאשר:
- אובייקט דורש פרמטרים אופציונליים או תלותיים רבים.
- בנייה כוללת מספר שלבים שעשויים להתבצע בסדר מסוים.
- אתה רוצה להשתמש באותו תהליך בנייה כדי ליצור גרסאות שונות של אובייקט.
- אין לחשוף את המצב הפנימי של אובייקט עד שהוא בנוי במלואו.
(ה) ,המושג היה רשמי על ידי ה-FLT:0.17.Gang of FourcioFLT:1 in their Point book in their ציון Book:2Design Patterns: Elements of Reusable Object-Oriented SoftwareFLT 3, ומאז הפך לרכיב מרכזי בפיתוח C#.com משמש באופן נרחב במסגרות כמו FLT:4, Entity FrameworkFLT5 for Building (R) ו-Furing Objects (R.
המונחים: the Builder Pattern
תבנית הרוכשת כוללת ארבעה משתתפים עיקריים:
- (ב) ,0) ייצור: 1 (האובייקט המורכב בבנייה) הוא מכיל לעתים קרובות חלקים רבים שיש להרכיבם.
- (ב) [המאה ה-1] [ה]] [התחילה] [ה] [ה]], [ה], [ה], [ה]], היא] ה'[ה], ו[ה]] [התורה] [ה']
- (FLT:0)ConcreteBuildFLT:1) - יישום ממשק הבונים לבנות ולהרכיב את החלקים של המוצר.זה ממשיך לעקוב אחר המוצר שנבנה ומספק דרך לאחזר את האובייקט המוגמר.
- (FLT:0)DirectorveFLT:1) - מציג את תהליך הבנייה על ידי קריאה לצעדי הבונים בסדר מסוים.הבמאי יודע את המתכון אך הוא עצמאי מהבנייה הבטונית, ומאפשר לאותו אלגוריתם לייצר ייצוגים שונים.
הלקוח בדרך כלל מסמיך בונה בטון, עובר אותו למנהל (או קורא לובן ישירות בסגנון רהוט), ולאחר מכן משחזר את המוצר המוגמר.
דוגמה: בניית בית מכס
בואו נלך דרך דוגמה מלאה, ניתנת לחזרה.נעצב מוצר (FLT:3) עם כמה תכונות אופציונליות.הבנייה תאפשר לנו ליצור צעד בית אחר צעד, ומנהל יאכפה רצף בנייה סטנדרטי.
שיעור המוצר
public class House
{
public string Foundation { get; set; }
public string Walls { get; set; }
public string Roof { get; set; }
public string Windows { get; set; }
public string Doors { get; set; }
public bool HasGarage { get; set; }
public bool HasGarden { get; set; }
public override string ToString()
=> $"House: {Walls}, {Roof}, {Doors}, {Windows}, Garage: {HasGarage}, Garden: {HasGarden}";
}
ממשק ה- Builder Interface
public interface IHouseBuilder
{
void BuildFoundation();
void BuildWalls();
void BuildRoof();
void BuildWindows();
void BuildDoors();
void BuildGarage();
void BuildGarden();
House GetResult();
}
בונה Concrete
public class ConcreteHouseBuilder : IHouseBuilder
{
private House _house = new House();
public void BuildFoundation() => _house.Foundation = "Concrete slab";
public void BuildWalls() => _house.Walls = "Brick walls";
public void BuildRoof() => _house.Roof = "Gable roof";
public void BuildWindows() => _house.Windows = "Double‑pane windows";
public void BuildDoors() => _house.Doors = "Wooden doors";
public void BuildGarage() => _house.HasGarage = true;
public void BuildGarden() => _house.HasGarden = true;
public House GetResult() => _house;
// Allow reset to reuse the builder
public void Reset() => _house = new House();
}
המנהל
public class HouseDirector
{
private IHouseBuilder _builder;
public HouseDirector(IHouseBuilder builder) => _builder = builder;
// Standard house construction steps
public House ConstructStandardHouse()
{
_builder.Reset();
_builder.BuildFoundation();
_builder.BuildWalls();
_builder.BuildRoof();
_builder.BuildWindows();
_builder.BuildDoors();
return _builder.GetResult();
}
// House with garage
public House ConstructHouseWithGarage()
{
_builder.Reset();
_builder.BuildFoundation();
_builder.BuildWalls();
_builder.BuildRoof();
_builder.BuildWindows();
_builder.BuildDoors();
_builder.BuildGarage();
return _builder.GetResult();
}
}
קוד הלקוח
var builder = new ConcreteHouseBuilder();
var director = new HouseDirector(builder);
House standardHouse = director.ConstructStandardHouse();
Console.WriteLine(standardHouse);
// Output: House: Brick walls, Gable roof, Wooden doors, Double‑pane windows, Garage: False, Garden: False
House houseWithGarage = director.ConstructHouseWithGarage();
Console.WriteLine(houseWithGarage);
// Output: House: Brick walls, Gable roof, Wooden doors, Double‑pane windows, Garage: True, Garden: False
דוגמה זו ממחישה כיצד התבנית מפרידה את "מה" (המוצר) מה"איך" (צעדי הבנייה) הבמאי יודע את הסדר, בעוד בונה בטון יודע איך ליצור כל חלק.
המונחים: differentation
בפיתוח C# מודרני, דפוס הבונים הקלאסי משולב לעתים קרובות עם ממשק (FLT:0) בעל השפעה 1 כדי לשפר את יכולת הקריאה. במקום להשתמש בבמאי, הנבנה עצמו חוזר FLT:9 מכל שלב, המאפשר שרשראות שיטה.זה פופולרי במיוחד בתצורה (למשל, FLT:10).
public class FluentHouseBuilder
{
private House _house = new House();
public FluentHouseBuilder WithFoundation(string type)
{
_house.Foundation = type;
return this;
}
public FluentHouseBuilder WithWalls(string material)
{
_house.Walls = material;
return this;
}
public FluentHouseBuilder WithRoof(string style)
{
_house.Roof = style;
return this;
}
public FluentHouseBuilder WithWindows(string type)
{
_house.Windows = type;
return this;
}
public FluentHouseBuilder WithDoors(string type)
{
_house.Doors = type;
return this;
}
public FluentHouseBuilder AddGarage() { _house.HasGarage = true; return this; }
public FluentHouseBuilder AddGarden() { _house.HasGarden = true; return this; }
public House Build() => _house;
}
// Usage
House modernHouse = new FluentHouseBuilder()
.WithFoundation("Concrete slab")
.WithWalls("Glass panels")
.WithRoof("Flat roof")
.WithWindows("Floor‑to‑ceiling")
.WithDoors("Sliding glass")
.AddGarage()
.Build();
בונה שוטפת מבטל את הצורך בבמאי נפרד ונותן ללקוח שליטה מלאה על רצף הבנייה.זה אידיאלי כאשר המוצר יש פרמטרים אופציונליים רבים ואתה לא צריך סדר בנייה שנקבע מראש.
מתי להשתמש בתבנית הלומדת
דפוס ה-Mader אינו תמיד הבחירה הטובה ביותר.חשבו בו כאשר:
- (ב) ל- 0 (Objects) יש שדות אופציונליים רבים או ריצוף מורכב.FLT:1 A בונה עם 10 + פרמטרים הופך ללא נאמנות וטעייה - פרון, הנבנה מאפשר לך להגדיר רק מה שאתה צריך.
- (FLT:0) ההרסה כוללת תהליך רב-שלבי.אנדרל:1; למשל, בניית דו"ח הדורש להביא נתונים, עיצוב והוספת ראשים/מרגלים.
- (ב) [ה]: [ה] צריך ליצור ייצוגים שונים של אותו חפץ.
- (ב) "אתה רוצה לאכוף צו בנייה מסוים של 1 בינואר, מבלי לחשוף את האובייקט בבנייה" (המנהל) יכול לאכוף את ה-FLT:14 נקרא לפני כן.
מצד שני, אם האובייקט שלך פשוט ויש לו כמה פרמטרים, בונה או שיטת מפעל סטטי הוא מספיק.הבנייה מוסיפה מורכבות כי לא מוצדק עבור מקרים טריוויאליים.
עיצוב לעומת תבניות אחרות
יצרן לעומת שיטת המפעל
דפוס ה-FLT:0 (FLT) של שיטת FLT:1 משמש כאשר בכיתה לא יכול לצפות את סוג האובייקטים שהיא חייבת ליצור.זה מעביר את ההרגעה ל- subclasses. מפעל בדרך כלל מחזיר אובייקט שלם בקריאה אחת, בעוד בונה בונה בונה בונה בונה את האובייקט על ידי צעד אחר צעד.
בונה לעומת המפעל
(FLT:0) המפעלים של אסטרקטל 1 מספק ממשק ליצירת משפחות של אובייקטים הקשורים (או תלויים) מבלי לציין את שיעורי הבטון שלהם.זה דומה לקבוצה של שיטות מפעל. aBuilder, לעומת זאת, מתמקד בבניית חפץ אחד מורכב.מפעל אבסטרקטי לעתים קרובות מחזיר מוצר גמור באופן מיידי, בעוד בונה מחזיר את האובייקט רק לאחר שנקראת הצעד הסופי.
בפועל, ניתן לשלב את שני החרושת מופשט: ניתן להשתמש בו כדי ליצור את הבונים עצמו (למשל, FLT:16), או בונה יכול להשתמש במפעל מופשט כדי ליצור חלקים בודדים של המוצר.
שימוש במקרים וריאציות
ג'נריק בונה עבור אובייקטים בלתי ניתנים למניעה
כאשר עובדים עם אובייקטים בלתי-מוגדרים (למשל, רשומות), הבונים יכולים לצבור מדינה ולאחר מכן לבנות את האובייקט הבלתי-מוגדר בשיטה של FLT:17; זה נפוץ בספריות כמו FLT:0FluentValidationFLT:1 או במהלך תצורה של FLT:2Htpientrated.
public record ProductConfiguration
{
public string Name { get; init; }
public decimal Price { get; init; }
public int Stock { get; init; }
public bool IsAvailable { get; init; }
}
public class ProductConfigurationBuilder
{
private string _name = "Default";
private decimal _price;
private int _stock;
private bool _isAvailable;
public ProductConfigurationBuilder WithName(string name) { _name = name; return this; }
public ProductConfigurationBuilder WithPrice(decimal price) { _price = price; return this; }
public ProductConfigurationBuilder WithStock(int stock) { _stock = stock; return this; }
public ProductConfigurationBuilder SetAvailability(bool available) { _isAvailable = available; return this; }
public ProductConfiguration Build()
=> new ProductConfiguration
{
Name = _name,
Price = _price,
Stock = _stock,
IsAvailable = _isAvailable
};
}
המונחים: תלותיות tube
באפליקציות של הארגון, בנינים לעתים קרובות צריכים להזריק שירותים.ניתן לרשום את הבונים במיכל DI ולתת לו להשיג את התלות הדרושה באמצעות הזרקת בנייה.הבנייה יכולה להשתמש בשירותים אלה במהלך הבנייה (למשל, בונה עבור FLT:19 אשר משתמש ב-FLT:20).
בונה שלב-ויז (Dialog Builder)
חלק מהחפצים דורשים בניית המוצר בחובה, בצעדים הכרחיים.במקרים כאלה ניתן ליצור בונה "צעד חכם" שרק חושף את הצעד הבא המותר.זה סוג של FLT:0state Machine EvolutionFLT:1 בתוך בונה, המשמש לעתים קרובות לבניית שאילתות או דיאלוגים.
ההליכים הטובים ביותר והמלכודות הנפוצות
- (FLT:0) שמור על המכוון של בונה (FLT:1) בונה צריך לבנות מוצר אחד.אם אתה צריך משפחות מוצר שונות, לשקול בנינים נפרדים או מפעל מופשט.
- (ב) לא צריך לקרוא לכל צעד, לא צריך להיקרא מוצר יש ברירת מחדל סבירה עבור חלקים אופציונליים.
- (ב) [13] ,0) ,התעד את המוצר הסופי בשיטה של FLT:21 .Felo 1: במקום לבדוק תוקף לאחר כל שלב, לאמת פעם אחת בסוף, אם המוצר אינו במצב תקף.
- (FLT:0) אי-ההתאמה של ההרחבה: 1 (FIRLT:1) לאחר שנבנה, המוצר צריך להיות בדרך כלל בלתי-מוגדר או יש ממשק מוגבל.
- (ב) ,0) ללא חשיפת המוצר במהלך הבנייה.
- (FLT:0) מעדיפים את הסגנון השוטף של מודרני C#irph:1 , בנאים פלורנטיים יותר להשתמש ולצמצם את הצורך בכיתה נפרדת.
טעות נפוצה היא להפוך את הבונים הגנרית מדי או לנסות לבנות מספר מוצרים שאינם קשורים עם אותו בונה. Stick to the Single אחריות עקרון: כל בונה בונה בונה סוג אחד של מוצר.
משאבים חיצוניים
כדי להעמיק את ההבנה של תבניות עיצוב עיצוב עיצוב ותבניות עיצוב היצרנים הכוללות, לחקור את ההפניות הסמכותיות הללו:
- (FLT:0) Microsoft Design Patterns (C#)FIRLT:1) - תיעוד רשמי עם דוגמאות.
- (ב) ,0) מתן גורו: בונה דפוסים של LT:1 , הסבר ברור עם דיאגרמות UML ו- pseudocode.
- מרטין פולר על Fluent InterfaceFillo 1 (צילום: רויטרס) - מתאר את הסגנון השוטף בשילוב עם בנינים.
מסקנה
תבנית בונה היא טכניקה עוצמתית ליצירת אובייקטים מורכבים ב C#. על ידי פיצול תהליך הבנייה לצעדים נפרדים, אתה מקבל שליטה טובה יותר, אחריות, בהירות בקוד שלך. בין אם אתה לאמץ את הגישה המבוססת על הבמאי הקלאסי או את בונה שוטפת מודרני יותר, התבנית מאפשרת לך להרכיב אובייקטים עם ביטחון - גם כאשר אובייקטים אלה יש רכיבים אופציונליים רבים, מתודולוגיה ראשונית, או מספר וריאציות.
זכרו כי אין דפוס הוא כדור כסף. להעריך את התרחיש הספציפי שלך: אם האובייקטים שלך פשוטים או אם מדרגות הבנייה לעתים רחוקות להשתנות, בונה או שיטת מפעל פשוט יותר.אבל כאשר אתה מוצא את עצמך היאבקות עם מבנים טלסקופים או ראשוניים מעונן עמוק, להגיע לתבנית הבונים.שימוש כראוי, זה יכול להפוך את הקוד שלך לתחזוקה יותר, ויזואלית, ומהנה לעבוד עם, במיוחד ביישומים בקנה מידה גדול.