ชั้นเรียนที่มีสมาชิกที่ไม่แน่นอนในระหว่างการสร้าง แต่ไม่เปลี่ยนรูปในภายหลัง


22

ฉันมีอัลกอริทึมที่สร้างชุดของวัตถุ วัตถุเหล่านี้ไม่แน่นอนในระหว่างการสร้างเนื่องจากมันเริ่มต้นด้วยการน้อยมาก แต่จากนั้นจะถูกเติมด้วยข้อมูลในสถานที่ต่าง ๆ ภายในอัลกอริทึม

หลังจากอัลกอริธึมเสร็จสมบูรณ์วัตถุไม่ควรเปลี่ยนแปลง - อย่างไรก็ตามมันถูกใช้โดยส่วนอื่น ๆ ของซอฟต์แวร์

ในสถานการณ์เหล่านี้ถือว่าเป็นแนวปฏิบัติที่ดีที่จะมีคลาสสองเวอร์ชันตามที่อธิบายไว้ด้านล่างหรือไม่

  • จากนั้นอัลกอริทึมจะถูกสร้างขึ้น
  • เมื่ออัลกอริทึมเสร็จสิ้นข้อมูลจะถูกคัดลอกไปยังวัตถุที่ไม่เปลี่ยนรูปซึ่งจะถูกส่งคืน

3
คุณสามารถแก้ไขคำถามเพื่ออธิบายปัญหา / คำถามของคุณได้อย่างไร
Simon Bergot

คำตอบ:


46

คุณอาจจะสามารถใช้รูปแบบการสร้าง มันใช้วัตถุ 'ผู้สร้าง' แยกต่างหากโดยมีวัตถุประสงค์ในการรวบรวมข้อมูลที่จำเป็นและเมื่อมีการรวบรวมข้อมูลทั้งหมดมันจะสร้างวัตถุจริง วัตถุที่สร้างขึ้นสามารถเปลี่ยนแปลงได้


โซลูชันของคุณเป็นโซลูชันที่ถูกต้องสำหรับความต้องการของฉัน (ไม่ใช่ทั้งหมดที่ระบุไว้) เมื่อตรวจสอบวัตถุที่ส่งคืนจะไม่ได้มีลักษณะเหมือนกันทั้งหมด คลาสตัวสร้างมีฟิลด์ที่สามารถ nullable ได้จำนวนมากและเมื่อข้อมูลถูกสร้างขึ้นคลาสตัวเลือกใดตัวเลือกหนึ่งใน 3 คลาสที่จะสร้าง: สิ่งเหล่านี้เกี่ยวข้องกันโดยการสืบทอด
Paul Richards

2
@ พอลในกรณีนี้หากคำตอบนี้ช่วยแก้ปัญหาของคุณได้คุณควรทำเครื่องหมายว่ายอมรับแล้ว
Riking

24

วิธีง่ายๆในการบรรลุเป้าหมายนี้คือมีอินเทอร์เฟซที่อนุญาตให้หนึ่งอ่านคุณสมบัติและเรียกวิธีอ่านอย่างเดียวเท่านั้นและคลาสที่ใช้อินเทอร์เฟซนั้นซึ่งช่วยให้คุณเขียนคลาสนั้นได้

วิธีการของคุณที่สร้างมันเกี่ยวข้องกับอดีตแล้วกลับหลังให้เพียงอินเตอร์เฟซแบบอ่านอย่างเดียวที่จะโต้ตอบ สิ่งนี้จะต้องไม่มีการคัดลอกและช่วยให้คุณสามารถปรับพฤติกรรมที่คุณต้องการให้ผู้โทรเห็นได้ง่ายขึ้นเมื่อเทียบกับผู้สร้าง

ใช้ตัวอย่างนี้:

public interface IPerson 
{
    public String FirstName 
    {
        get;
    }

    public String LastName 
    {
        get;
    }
} 

public class PersonImpl : IPerson 
{
    private String firstName, lastName;

    public String FirstName 
    {
        get { return firstName; }
        set { firstName = value; }
    }

    public String LastName 
    {
        get { return lastName; }
        set { lastName = value; }
    }
}

class Factory 
{
    public IPerson MakePerson() 
    {
        PersonImpl person = new PersonImpl();
        person.FirstName = 'Joe';
        person.LastName = 'Schmoe';
        return person;
    }
}

ข้อเสียเปรียบเพียงอย่างเดียวของวิธีการนี้คือการที่ใคร ๆ ก็สามารถโยนมันไปยังชั้นเรียนการใช้งาน ถ้ามันเป็นเรื่องของความปลอดภัยแล้วการใช้วิธีนี้ก็ไม่เพียงพอ วิธีแก้ปัญหาสำหรับสิ่งนี้คือคุณสามารถสร้างคลาสfacadeเพื่อตัดคลาสที่ไม่แน่นอนซึ่งจะแสดงอินเตอร์เฟสที่ผู้เรียกใช้ด้วยและไม่สามารถเข้าถึงวัตถุภายในได้

ด้วยวิธีนี้การไม่แคสติ้งจะช่วยคุณได้ ทั้งคู่สามารถได้รับจากอินเทอร์เฟซแบบอ่านอย่างเดียวเท่านั้น แต่การส่งคืนออบเจ็กต์จะให้คลาส Facade แก่คุณซึ่งไม่เปลี่ยนรูปเนื่องจากไม่เปลี่ยนสถานะพื้นฐานของคลาสที่ไม่แน่นอน

เป็นมูลค่าการกล่าวขวัญว่าสิ่งนี้ไม่เป็นไปตามแนวโน้มทั่วไปที่วัตถุไม่เปลี่ยนรูปจะถูกสร้างขึ้นเพียงครั้งเดียวและผ่านตัวสร้าง คุณอาจต้องจัดการกับพารามิเตอร์หลายตัว แต่คุณควรถามตัวเองว่าพารามิเตอร์เหล่านี้ทั้งหมดจำเป็นต้องมีการกำหนดไว้ล่วงหน้าหรืออาจมีการแนะนำบางอย่างในภายหลัง ในกรณีนี้ควรใช้ตัวสร้างแบบง่ายพร้อมพารามิเตอร์ที่จำเป็นเท่านั้น กล่าวอีกนัยหนึ่งอย่าใช้รูปแบบนี้หากมีการครอบคลุมถึงปัญหาอื่นในโปรแกรมของคุณ


1
ความปลอดภัยไม่ดีขึ้นหากส่งคืนวัตถุ "อ่านอย่างเดียว" เนื่องจากรหัสที่รับวัตถุนั้นยังคงสามารถปรับเปลี่ยนวัตถุได้โดยใช้การสะท้อนกลับ แม้กระทั่งสตริงที่สามารถแก้ไขได้ (ไม่คัดลอกแก้ไขในสถานที่) โดยใช้การสะท้อน
MTilsted

ปัญหาด้านความปลอดภัยสามารถแก้ไขได้อย่างเรียบร้อยด้วยชั้นเรียนส่วนตัว
Esben Skov Pedersen

@Esben: คุณยังคงต้องต่อสู้กับMS07-052: รหัสผลการดำเนินการในการเรียกใช้โค้ด รหัสของคุณกำลังทำงานในบริบทความปลอดภัยเดียวกันกับรหัสของพวกเขาดังนั้นพวกเขาสามารถแนบดีบักเกอร์และทำสิ่งที่พวกเขาต้องการ
Kevin

Kevin1 คุณสามารถพูดได้ว่าเกี่ยวกับการห่อหุ้มทั้งหมด ฉันไม่ได้พยายามป้องกันการสะท้อน
Esben Skov Pedersen

1
ปัญหาของการใช้คำว่า "ความปลอดภัย" ก็คือทันทีที่มีคนสันนิษฐานว่าสิ่งที่ฉันพูดว่าเป็นตัวเลือกที่ปลอดภัยยิ่งขึ้นนั้นเทียบเท่ากับความปลอดภัยสูงสุดและแนวปฏิบัติที่ดีที่สุด ฉันไม่เคยพูดเช่นกัน หากคุณมอบห้องสมุดให้ใครบางคนใช้นอกเสียจากว่า obfuscated (และบางครั้งแม้เมื่อ obfuscated) คุณสามารถลืมเกี่ยวกับการรับประกันความปลอดภัย อย่างไรก็ตามฉันคิดว่าเราทุกคนสามารถเห็นด้วยกับความจริงที่ว่าถ้าคุณยุ่งกับวัตถุที่ส่งคืนโดยใช้การสะท้อนกลับเพื่อดึงวัตถุภายในที่มีอยู่ภายในซึ่งคุณไม่ได้ใช้ไลบรารีอย่างที่ควรจะเป็น
Neil

8

คุณสามารถใช้รูปแบบการสร้างเป็น @JacquesB กล่าวหรือหรือคิดว่าทำไมมันเป็นจริงว่าวัตถุเหล่านี้ของคุณมีที่จะไม่แน่นอนในระหว่างการสร้าง?

กล่าวอีกนัยหนึ่งทำไมกระบวนการสร้างพวกเขาจึงต้องแพร่กระจายในเวลาตรงข้ามกับการส่งผ่านค่าที่ต้องการทั้งหมดเข้าไปในตัวสร้างและการสร้างอินสแตนซ์ในครั้งเดียว

เพราะตัวสร้างอาจเป็นทางออกที่ดีสำหรับปัญหาที่ผิด

หากปัญหาคือคุณท้ายด้วยตัวสร้างที่มีความยาว 10 พารามิเตอร์และคุณต้องการลดมันด้วยการสร้างวัตถุทีละเล็กทีละน้อยก็อาจบ่งบอกว่าการออกแบบนั้นมีความยุ่งเหยิงและค่า 10 ค่านี้ควรเป็น " bagged "/ จัดกลุ่มเป็นวัตถุสองสามอย่าง ... หรือวัตถุหลักแบ่งออกเป็นวัตถุขนาดเล็กกว่าสองสาม ...

ในกรณีนี้ - ยึดติดกับสิ่งที่เปลี่ยนแปลงไม่ได้ตลอดทางเพียงแค่ปรับปรุงการออกแบบ


มันจะเป็นการยากที่จะสร้างมันขึ้นมาทั้งหมดในครั้งเดียวเนื่องจากโค้ดจะทำการสืบค้นหลาย ๆ ฐานข้อมูลเพื่อรับข้อมูล มันเปรียบเทียบข้อมูลในตารางที่แตกต่างกันและในฐานข้อมูลที่แตกต่างกัน
Paul Richards
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.