Việc sử dụng làm cho constructor riêng tư trong một lớp là gì?


134

Tại sao chúng ta nên làm cho constructor riêng trong lớp? Vì chúng ta luôn cần các nhà xây dựng được công khai.

Câu trả lời:


129

Một số lý do mà bạn có thể cần nhà xây dựng riêng:

  1. Hàm xây dựng chỉ có thể được truy cập từ phương thức nhà máy tĩnh bên trong chính lớp đó. Singleton cũng có thể thuộc thể loại này.
  2. Một lớp tiện ích , chỉ chứa các phương thức tĩnh.

9
Tôi thậm chí sẽ không bận tâm đến việc tạo một hàm tạo riêng cho một lớp tiện ích.
Petesh

16
@Patesh: Đó là quyết định của bạn. Những người khác và tôi thà ngăn chặn việc khởi tạo lớp tiện ích hơn là bỏ qua một hàm tạo riêng.
nanda

1
trong một số ngôn ngữ lập trình (đáng chú ý là Java), nó cũng ngăn chặn sự kế thừa
dfa

9
@dfa: để ngăn chặn sự kế thừa, bạn phải đưa finallên cấp độ lớp học. Đặt constructor riêng là khá nhiều vô dụng vì lý do này.
nanda

3
@ Will: Không nếu bạn sử dụng sự phản chiếu. Khai báo các hàm tạo riêng tư nhằm ngăn chặn việc khởi tạo (chặn phản xạ), nhưng ngăn chặn phân lớp là một tác dụng phụ, không phải là ý định. Công cụ thích hợp cho việc này là khai báo lớp final. Đây là những gì Sun đã làm cho lớp String và một đoạn API hợp lý không nên được mở rộng.
BobMcGee

96

Bằng cách cung cấp một hàm tạo riêng, bạn ngăn các thể hiện của lớp được tạo ở bất kỳ nơi nào khác ngoài chính lớp này. Có một số trường hợp sử dụng để cung cấp hàm tạo như vậy.

A. Các thể hiện lớp của bạn được tạo trong một staticphương thức. Các staticphương pháp sau đó được khai báo là public.

class MyClass()
{
private:
  MyClass() { }

public:
  static MyClass * CreateInstance() { return new MyClass(); }
};

B. Lớp của bạn là một người độc thân . Điều này có nghĩa, không có nhiều hơn một thể hiện của lớp bạn trong chương trình.

class MyClass()
{
private:
  MyClass() { }

public:
  MyClass & Instance()
  {
    static MyClass * aGlobalInst = new MyClass();
    return *aGlobalInst;
  }
};

C. (Chỉ áp dụng cho tiêu chuẩn C ++ 0x sắp tới) Bạn có một số hàm tạo. Một số trong số họ được tuyên bố public, những người khác private. Để giảm kích thước mã, các nhà xây dựng công cộng 'gọi' các nhà xây dựng riêng tư lần lượt thực hiện tất cả công việc. publicDo đó, các hàm tạo của bạn được gọi là các hàm tạo ủy nhiệm :

class MyClass
{
public:
  MyClass() : MyClass(2010, 1, 1) { }

private:
  MyClass(int theYear, int theMonth, int theDay) { /* do real work */ }
};

D. Bạn muốn hạn chế sao chép đối tượng (ví dụ: vì sử dụng tài nguyên được chia sẻ):

class MyClass
{
  SharedResource * myResource;

private:
  MyClass(const MyClass & theOriginal) { }
};

E. Lớp của bạn là một lớp tiện ích . Điều đó có nghĩa, nó chỉ chứa staticcác thành viên. Trong trường hợp này, không có đối tượng nào phải được tạo trong chương trình.


3
Trong hầu hết các trường hợp, bạn sẽ muốn ngăn chặn việc sao chép đối tượng. Vì vậy, bạn sẽ không cung cấp một triển khai cho các nhà xây dựng bản sao riêng tư.
frast

từ hướng dẫn kiểu google c ++ (một ví dụ khác không có trong danh sách nhưng phổ biến) -> nếu bạn cần thực hiện công việc trong hàm tạo "hãy xem xét hàm của nhà máy [và đặt hàm tạo riêng tư]" (văn bản trong dấu ngoặc vuông được viết bởi tôi )
Trevor Boyd Smith

12

Để lại một "cửa sau" cho phép một lớp / chức năng bạn bè khác xây dựng một đối tượng theo cách bị cấm đối với người dùng. Một ví dụ xuất hiện trong tâm trí sẽ là một thùng chứa xây dựng một trình vòng lặp (C ++):

Iterator Container::begin() { return Iterator(this->beginPtr_); }
// Iterator(pointer_type p) constructor is private,
//     and Container is a friend of Iterator.

Điều này có đủ khác không, Terry? ;)
Cormier Emile

Câu trả lời tốt. Tại sao không đề cập đến sự phản chiếu, vì đây là một con đường để hoàn thành một cái gì đó mà người dùng không thể?
BobMcGee

@Bob: Bạn sẽ phải khai sáng cho tôi về điều đó, vì tôi chủ yếu là một anh chàng C ++ và sự phản chiếu không thực sự có trong từ vựng của C ++. ;)
Cormier Emile

3
Không ai sẽ đọc điều này, nhưng ở đây đi: Tôi đã bị đánh giá thấp một vài lần về điều này. Không buồn bã hay bất cứ điều gì, nhưng (vì lợi ích của việc học) Tôi muốn biết tại sao điều này là xấu? Làm thế nào khác một trình vòng lặp có thể được xây dựng với dữ liệu mà nó cần để truy cập dữ liệu của bộ chứa?
Cileier Cormier

2
@EmileCormier, tôi nghĩ bạn đã bỏ phiếu không công bằng vì những người học C ++ được nói đi nói lại: "Tránh tuyên bố bạn bè". Lời khuyên này dường như nhằm vào các lập trình viên C ++ thiếu kinh nghiệm, những người có thể sử dụng friendở nơi không được bảo hành và có rất nhiều trường hợp đó là một ý tưởng tồi. Đáng buồn thay, thông điệp đã được đón nhận quá tốt và nhiều nhà phát triển không bao giờ học ngôn ngữ đủ tốt để hiểu rằng việc sử dụng không thường xuyên friendkhông chỉ được chấp nhận, mà còn tốt hơn . Ví dụ của bạn chỉ là một trường hợp như vậy. Cố ý khớp nối mạnh mẽ là không có tội, đó là một quyết định thiết kế.
evadeflow

10

Mọi người bị mắc kẹt vào điều Singleton, wow.

Những thứ khác:

  • Ngăn chặn mọi người tạo lớp của bạn trên ngăn xếp; làm cho các nhà xây dựng tư nhân và chỉ quay lại con trỏ thông qua một phương pháp nhà máy.
  • Ngăn chặn việc tạo các bản sao của lớp (hàm tạo bản sao riêng)

8

Điều này có thể rất hữu ích cho một hàm tạo có chứa mã chung; Các hàm tạo riêng có thể được gọi bởi các hàm tạo khác, sử dụng 'this (...);' ký hiệu. Bằng cách tạo mã khởi tạo chung trong một hàm tạo riêng tư (hoặc được bảo vệ), bạn cũng đang làm rõ ràng rằng nó chỉ được gọi trong khi xây dựng, điều này không phải vậy nếu nó chỉ đơn giản là một phương thức:

public class Point {
   public Point() {
     this(0,0); // call common constructor
   }
   private Point(int x,int y) {
     m_x = x; m_y = y;
   }
};

3

Có một số trường hợp bạn có thể không muốn sử dụng một hàm tạo công khai; ví dụ nếu bạn muốn một lớp singleton.

Nếu bạn đang viết một hội đồng được sử dụng bởi các bên thứ 3, có thể có một số lớp bên trong mà bạn chỉ muốn được tạo bởi hội đồng của bạn và không được người dùng của hội đồng của bạn tạo ra.


3

Điều này đảm bảo rằng bạn (lớp có hàm tạo riêng) kiểm soát cách gọi của bộ điều khiển.

Một ví dụ: Một phương thức nhà máy tĩnh trên lớp có thể trả về các đối tượng khi phương thức nhà máy chọn để phân bổ chúng (ví dụ như một nhà máy đơn lẻ).


@Skilldrick: một ví dụ sẽ là bạn có thể buộc một lớp chỉ được phân bổ heap.
Dirk

@dirk Tôi đã xóa bình luận của mình vì nó không còn phù hợp.
Skilldrick

3

Chúng ta cũng có thể có hàm tạo riêng, để chỉ tạo ra đối tượng theo một lớp cụ thể (Vì lý do bảo mật).

Một cách để làm điều đó là thông qua việc có một lớp bạn bè.

Ví dụ về C ++:

class ClientClass;
class SecureClass 
{
  private:
    SecureClass();   // Constructor is private.
    friend class ClientClass;  // All methods in 
                               //ClientClass have access to private
                               // &   protected methods of SecureClass.
};

class ClientClass
{
public:
    ClientClass();
    SecureClass* CreateSecureClass()
     { 
           return (new SecureClass());  // we can access 
                                        // constructor of 
                                        // SecureClass as 
                                        // ClientClass is friend 
                                        // of SecureClass.
     }
};

Lưu ý: Lưu ý: Chỉ ClientClass (vì nó là bạn của SecureClass) mới có thể gọi Trình xây dựng của SecureClass.



2

Khi bạn không muốn người dùng tạo các thể hiện của lớp này hoặc tạo lớp kế thừa lớp này, như java.lang.math, tất cả các hàm trong gói này là static, tất cả các hàm có thể được gọi mà không cần tạo một thể hiện math, do đó, hàm tạo được thông báo là tĩnh .


1

Nếu nó là riêng tư, thì bạn không thể gọi nó ==> bạn không thể khởi tạo lớp. Hữu ích trong một số trường hợp, như một singleton.

Có một cuộc thảo luận và một số ví dụ nữa ở đây .


1

Tôi thấy một câu hỏi từ bạn giải quyết vấn đề tương tự.

Đơn giản là nếu bạn không muốn cho phép những người khác tạo phiên bản, thì hãy giữ nguyên tắc trong phạm vi giới hạn. Ứng dụng thực tế (Một ví dụ) là mẫu singleton.


1

Bạn không nên đặt công cụ xây dựng riêng tư. Giai đoạn = Stage. Làm cho nó được bảo vệ, vì vậy bạn có thể mở rộng lớp nếu bạn cần.

Chỉnh sửa: Tôi đang đứng trước điều đó, bất kể bạn ném bao nhiêu lần vào đây. Bạn đang cắt đứt tiềm năng phát triển mã trong tương lai. Nếu người dùng hoặc lập trình viên khác thực sự quyết tâm mở rộng lớp, thì họ sẽ chỉ thay đổi hàm tạo thành được bảo vệ trong nguồn hoặc mã byte. Bạn sẽ không làm được gì ngoài việc làm cho cuộc sống của họ khó khăn hơn một chút. Bao gồm một cảnh báo trong ý kiến ​​của nhà xây dựng của bạn và để nó ở đó.

Nếu đó là một lớp tiện ích, giải pháp đơn giản hơn, chính xác hơn và thanh lịch hơn là đánh dấu toàn bộ "lớp cuối cùng tĩnh" để ngăn chặn sự mở rộng. Nó không làm gì tốt khi chỉ đánh dấu nhà xây dựng riêng tư; một người dùng thực sự xác định có thể luôn luôn sử dụng sự phản chiếu để có được hàm tạo.

Sử dụng hợp lệ:

  • Một cách sử dụng tốt của hàm protected tạo là bắt buộc sử dụng các phương thức tĩnh của nhà máy, cho phép bạn hạn chế khởi tạo hoặc nhóm và sử dụng lại các tài nguyên đắt tiền (kết nối DB, tài nguyên riêng).
  • Singletons (thường không thực hành tốt, nhưng đôi khi cần thiết)

2
Theo kinh nghiệm của tôi không có sự thật tuyệt đối, thậm chí goto có thể được sử dụng nếu tình huống yêu cầu. Có những cách xấu và xấu, nhưng như Marshall Cline đã nói, đôi khi bạn cần phải chọn giữa những tệ nạn nhỏ hơn. parashift.com/c++-faq-lite/big-picture.html#faq-6.15 Đối với các nhà xây dựng tư nhân, chúng là cần thiết và thậm chí không tệ cho bạn. Nó chỉ có nghĩa là không ai, kể cả các lớp con của bạn nên sử dụng nó.
daramarak

Gotos có vị trí của họ, đúng, nhưng đánh dấu một nhà xây dựng riêng tư giúp bạn không có gì ngoài những rắc rối trên đường. Tôi đã chỉnh sửa bài viết của mình để giải thích đầy đủ hơn tại sao.
BobMcGee

Nó không có ý nghĩa để sao chép xây dựng hoặc mặc định xây dựng một số lớp. Trong C ++, bạn chỉ ra điều này bằng cách khai báo một ctor riêng mà không xác định nó (điều này cũng phổ biến cho toán tử =).

Tối ưu hóa các trình biên dịch như Java JIT và GWT thực sự sử dụng các hàm tạo riêng: để giới hạn phạm vi khởi tạo và thực hiện công việc tốt hơn trong việc sắp xếp / cắt xén mã của bạn.
Ajax

1

Trình xây dựng là riêng tư cho một số mục đích như khi bạn cần triển khai singleton hoặc giới hạn số lượng đối tượng của một lớp. Ví dụ trong triển khai singleton, chúng ta phải đặt constructor ở chế độ riêng tư

#include<iostream>
using namespace std;
class singletonClass
{


    static int i;
    static singletonClass* instance;
public:


    static singletonClass* createInstance()
    {


        if(i==0)
        {

            instance =new singletonClass;
            i=1;

        }

        return instance;

    }
    void test()
    {

        cout<<"successfully created instance";
    }
};

int singletonClass::i=0;
singletonClass* singletonClass::instance=NULL;
int main()
{


    singletonClass *temp=singletonClass::createInstance();//////return instance!!!
    temp->test();
}

Một lần nữa nếu bạn muốn giới hạn việc tạo đối tượng tối đa 10 thì hãy sử dụng như sau

#include<iostream>
using namespace std;
class singletonClass
{


    static int i;
    static singletonClass* instance;
public:


    static singletonClass* createInstance()
    {


        if(i<10)
        {

            instance =new singletonClass;
            i++;
            cout<<"created";

        }

        return instance;

    }
};

int singletonClass::i=0;
singletonClass* singletonClass::instance=NULL;
int main()
{


    singletonClass *temp=singletonClass::createInstance();//return an instance
    singletonClass *temp1=singletonClass::createInstance();///return another instance

}

Cảm ơn


1

Bạn có thể có nhiều hơn một constructor. C ++ cung cấp một hàm tạo mặc định và một hàm tạo sao chép mặc định nếu bạn không cung cấp một hàm rõ ràng. Giả sử bạn có một lớp chỉ có thể được xây dựng bằng cách sử dụng một số hàm tạo tham số. Có lẽ nó khởi tạo biến. Nếu người dùng sau đó sử dụng lớp này mà không có hàm tạo đó, họ có thể không gây ra sự cố. Một quy tắc chung tốt: Nếu việc triển khai mặc định không hợp lệ, hãy đặt cả hàm tạo mặc định và sao chép thành riêng tư và không cung cấp triển khai:

class C
{
public:
    C(int x);

private:
    C();
    C(const C &);
};

Sử dụng trình biên dịch để ngăn người dùng sử dụng đối tượng với các hàm tạo mặc định không hợp lệ.


2
Khi bạn cung cấp một hàm tạo không mặc định mà không chỉ định hàm tạo mặc định, hàm tạo mặc định sẽ không tồn tại. Không cần phải tạo ra nó và làm cho nó riêng tư.
TT_

0

Trích dẫn từ Java hiệu quả , bạn có thể có một lớp với hàm tạo riêng để có một lớp tiện ích xác định các hằng số (như các trường cuối cùng tĩnh).

( EDIT: Theo nhận xét, đây là điều có thể chỉ áp dụng được với Java, tôi không biết liệu cấu trúc này có thể áp dụng / cần thiết trong các ngôn ngữ OO khác hay không (giả sử C ++))

Một ví dụ như dưới đây:

public class Constants {
    private Contants():

    public static final int ADDRESS_UNIT = 32;
    ...
}

EDIT_1 : Một lần nữa, giải thích bên dưới được áp dụng trong Java: (và tham khảo từ cuốn sách, Java hiệu quả )

Một khởi tạo của lớp tiện ích như lớp bên dưới, mặc dù không có hại, không phục vụ bất kỳ mục đích nào vì chúng không được thiết kế để khởi tạo.

Ví dụ, giả sử không có Trình xây dựng riêng cho các hằng số lớp. Một đoạn mã như dưới đây là hợp lệ nhưng không truyền đạt tốt hơn ý định của người dùng lớp Hằng

unit = (this.length)/new Constants().ADDRESS_UNIT;

trái ngược với mã như

unit = (this.length)/Constants.ADDRESS_UNIT;

Ngoài ra tôi nghĩ rằng một nhà xây dựng tư nhân truyền đạt ý định của người thiết kế lớp Hằng (nói) tốt hơn.

Java cung cấp một hàm tạo công khai không tham số mặc định nếu không có hàm tạo nào được cung cấp và nếu ý định của bạn là ngăn chặn việc khởi tạo thì cần một hàm tạo riêng.

Người ta không thể đánh dấu một lớp tĩnh cấp cao nhất và thậm chí một lớp cuối cùng có thể được khởi tạo.


2
Nhưng trong C ++, bạn không cần một lớp cho việc này. Nếu một cái gì đó không phụ thuộc vào dữ liệu bên trong đối tượng, hãy viết nó dưới dạng các hàm miễn phí và các biến miễn phí. Muốn đóng gói? Sử dụng một không gian tên.
daramarak

@daramarak: cảm ơn, tôi chưa có kinh nghiệm với C ++. Tôi đã cập nhật câu trả lời để phản ánh rằng điều này chỉ có thể áp dụng trong Java
sateesh

2
Nếu đối tượng của bạn chỉ đóng gói các biến tĩnh, tại sao lại giới hạn khởi tạo? Tại sao chỉ định bất cứ điều gì về các nhà xây dựng? Nó sẽ không gây hại gì nếu nó được khởi tạo. Có vẻ như bạn có thể nhận được kết quả tương tự khi khai báo lớp tĩnh và cuối cùng.
BobMcGee

@BobMcGee, cảm ơn vì nhận xét của bạn. Điều này khiến tôi phải suy nghĩ (và tham khảo) nhiều hơn về những gì tôi đã đăng. Tôi đã chỉnh sửa câu trả lời của mình để thêm một số lý do về tính hữu ích của hàm tạo riêng.
sateesh

0

Các lớp tiện ích có thể có các nhà xây dựng tư nhân. Người dùng của các lớp sẽ không thể khởi tạo các lớp này:

public final class UtilityClass {
    private UtilityClass() {}

    public static utilityMethod1() {
        ...
    }
}

1
Tại sao nó không quan trọng nếu lớp tiện ích được khởi tạo? Tất cả những gì nó làm là tạo một đối tượng không có trường và ăn một vài byte bộ nhớ.
BobMcGee

Có thể khởi tạo nó tạo ra một API mơ hồ. Nếu bạn thiết kế một lớp là một lớp tiện ích không có trạng thái và muốn giữ nó theo cách đó. Bạn có thể phân lớp một lớp với một hàm tạo công khai. Một lớp con của một số phương thức tiện ích là ngu ngốc.
gpampara

@BobMcGee: rõ ràng thiết kế một lớp hoạt động và thiết kế một lớp để người khác sử dụng là những điều khác nhau. Những người làm việc trong phát triển API (chẳng hạn như người mặt trời hoặc anh chàng bộ sưu tập Google) sẽ giết bất cứ ai cố gắng nói rằng nhà xây dựng riêng tư trong một lớp tiện ích là vô dụng.
nanda

@gpampara: Khai báo lớp cuối cùng của bạn ngăn mọi người phân lớp. Đây là những gì Sun đã làm cho lớp String. @Nanda: Một lớp tiện ích không cần một hàm tạo xác định. Nếu bạn không muốn nó có thể mở rộng, thì hãy tuyên bố nó không tồn tại bằng cách sử dụng "bản cuối cùng".
BobMcGee

1
@BobMcGee: Bạn có vẻ thích xem ví dụ từ Sun. Sau đó kiểm tra lớp Bộ sưu tập tiện ích này từ Sun: docjar.com/html/api/java/util/Collections.java.html . Đó thực sự là sử dụng nhà xây dựng tư nhân.
nanda

0

Bạn có thể muốn ngăn chặn một lớp được khởi tạo tự do. Xem mẫu thiết kế singleton làm ví dụ. Để đảm bảo tính duy nhất, bạn không thể cho phép bất kỳ ai tạo phiên bản của nó :-)


0

Một trong những ứng dụng quan trọng là trong lớp SingleTon

class Person
{
   private Person()
   {
      //Its private, Hense cannot be Instantiated
   }

   public static Person GetInstance()
   {
       //return new instance of Person
       // In here I will be able to access private constructor
   }
};

Nó cũng phù hợp, Nếu lớp của bạn chỉ có các phương thức tĩnh. tức là không ai cần phải khởi tạo lớp của bạn


Cần lưu ý rằng singleton được nhiều người coi là "chống mẫu" và quyết định áp dụng nó không nên được đưa ra một cách nhẹ nhàng. Một thay thế phổ biến là tiêm phụ thuộc.
Michael Aaron Safyan

SingleTon không phải là một mô hình chống. tuy nhiên, việc sử dụng mẫu quá mức (vì thiếu kiến ​​thức về việc sử dụng nó) là không tốt. Cần lưu ý rằng một trong những mẫu GOF.
SysAdmin

0

Đó thực sự là một lý do rõ ràng: bạn muốn xây dựng một đối tượng, nhưng nó không thực tế để làm điều đó (về mặt giao diện) trong hàm tạo.

Các Factoryví dụ là khá rõ ràng, hãy để tôi chứng minh Named Constructorthành ngữ.

Nói rằng tôi có một lớp Complexcó thể đại diện cho một số phức.

class Complex { public: Complex(double,double); .... };

Câu hỏi đặt ra là: liệu nhà xây dựng có mong đợi phần thực và phần ảo hay không, hay nó mong đợi định mức và góc (tọa độ cực)?

Tôi có thể thay đổi giao diện để làm cho nó dễ dàng hơn:

class Complex
{
public:
  static Complex Regular(double, double = 0.0f);
  static Complex Polar(double, double = 0.0f);
private:
  Complex(double, double);
}; // class Complex

Đây được gọi là Named Constructorthành ngữ: lớp chỉ có thể được xây dựng từ đầu bằng cách nêu rõ ràng hàm tạo nào chúng ta muốn sử dụng.

Đó là một trường hợp đặc biệt của nhiều phương pháp xây dựng. Các mẫu thiết kế cung cấp một số lượng tốt của cách để xây dựng đối tượng: Builder, Factory, Abstract Factory, ... và xây dựng tư nhân sẽ đảm bảo rằng người dùng bị hạn chế đúng cách.


0

Ngoài những công dụng được biết đến nhiều hơn

Để triển khai mẫu Phương thức đối tượng mà tôi tóm tắt là:

“Constructor tư nhân, phương pháp tĩnh công cộng”
“Object để thực hiện, chức năng cho giao diện”

Nếu bạn muốn thực hiện một hàm bằng cách sử dụng một đối tượng và đối tượng không hữu ích ngoài việc thực hiện tính toán một lần (bằng cách gọi phương thức), thì bạn có Đối tượng Ném đi . Bạn có thể gói gọn việc tạo đối tượng và gọi phương thức trong một phương thức tĩnh, ngăn chặn kiểu chống phổ biến này:

z = new A(x,y).call();

Thay thế nó bằng một cuộc gọi chức năng (không gian tên):

z = A.f(x,y);

Người gọi không bao giờ cần biết hoặc quan tâm rằng bạn đang sử dụng một đối tượng bên trong, mang lại giao diện sạch hơn và ngăn rác từ đối tượng treo xung quanh hoặc sử dụng đối tượng không chính xác.

Ví dụ, nếu bạn muốn chia tay một tính toán trên phương pháp foo, barzork, ví dụ trạng thái cổ phiếu mà không cần phải vượt qua nhiều giá trị trong và ngoài chức năng, bạn có thể thực hiện nó như sau:

class A {
  public static Z f(x, y) {
    A a = new A(x, y);
    a.foo();
    a.bar();
    return a.zork();
  }

  private A(X x, Y y) { /* ... */ };
}

Mẫu Đối tượng Phương thức này được đưa ra trong Các mẫu thực hành tốt nhất của Smalltalk , Kent Beck, trang 34 Ném37, trong đó đây là bước cuối cùng của mẫu tái cấu trúc, kết thúc:

  1. Thay thế phương thức ban đầu bằng một phương thức tạo ra một thể hiện của lớp mới, được xây dựng với các tham số và bộ thu của phương thức ban đầu và gọi ra tính toán điện tử.

Điều này khác biệt đáng kể so với các ví dụ khác ở đây: lớp có thể thực hiện được (không giống như lớp tiện ích), nhưng các thể hiện là riêng tư (không giống như các phương thức của nhà máy, bao gồm cả singletons, v.v.) và có thể sống trên stack, vì chúng không bao giờ thoát.

Mẫu này rất hữu ích trong OOP từ dưới lên, trong đó các đối tượng được sử dụng để đơn giản hóa việc thực hiện ở mức độ thấp, nhưng không nhất thiết phải lộ ra bên ngoài và tương phản với OOP từ trên xuống thường được trình bày và bắt đầu với giao diện cấp cao.


0

Đôi khi rất hữu ích nếu bạn muốn kiểm soát các trường hợp (và bao nhiêu) đối tượng được tạo.

Trong số những người khác, được sử dụng trong các mẫu:

Singleton pattern
Builder pattern

Làm thế nào là một nhà xây dựng tư nhân hữu ích trong một đối tượng bất biến? Tính không thay đổi là về việc ngăn chặn các thay đổi đối với một đối tượng sau khi tạo , trong khi các nhà xây dựng tư nhân là về việc ngăn chặn việc tạo .
Nils von Barth

0

Việc sử dụng các nhà xây dựng tư nhân cũng có thể là để tăng khả năng đọc / bảo trì khi đối mặt với thiết kế hướng tên miền. Từ "Microsoft .NET - Ứng dụng Architecing cho doanh nghiệp, Phiên bản 2":

var request = new OrderRequest(1234);

Trích dẫn: "Có hai vấn đề ở đây. Đầu tiên, khi nhìn vào mã, người ta khó có thể đoán được chuyện gì đang xảy ra. Một phiên bản của OrderRequest đang được tạo, nhưng tại sao và sử dụng dữ liệu nào? Cái gì 1234? Điều này dẫn đến vấn đề thứ hai: Bạn đang vi phạm ngôn ngữ phổ biến của bối cảnh bị ràng buộc. Ngôn ngữ có thể nói như thế này: khách hàng có thể đưa ra yêu cầu đặt hàng và được phép chỉ định ID mua hàng. Nếu đó là cách tốt hơn để có được một ví dụ OrderRequest mới : "

var request = OrderRequest.CreateForCustomer(1234);

Ở đâu

private OrderRequest() { ... }

public OrderRequest CreateForCustomer (int customerId)
{
    var request = new OrderRequest();
    ...
    return request;
}

Tôi không ủng hộ điều này cho mỗi lớp duy nhất, nhưng đối với kịch bản DDD ở trên, tôi nghĩ rằng nó có ý nghĩa hoàn hảo để ngăn chặn việc tạo trực tiếp một đối tượng mới.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.