Jaki jest pożytek z uczynienia konstruktora prywatnym w klasie?

134

Dlaczego powinniśmy uczynić konstruktora prywatnym w klasie? Ponieważ zawsze potrzebujemy, aby konstruktor był publiczny.

giri
źródło

Odpowiedzi:

129

Niektóre powody, dla których możesz potrzebować prywatnego konstruktora:

  1. Dostęp do konstruktora można uzyskać tylko za pomocą statycznej metody fabrycznej wewnątrz samej klasy. Singleton również może należeć do tej kategorii.
  2. Klasa narzędziowa , która zawiera tylko metody statyczne.
nanda
źródło
9
Nie zawracałbym sobie nawet głowy tworzeniem prywatnego konstruktora dla klasy użytkowej.
Petesh
16
@Patesh: To twoja decyzja. Inni i ja wolelibyśmy raczej zapobiec tworzeniu instancji klasy użytkowej niż pominąć jeden wiersz konstruktora prywatnego.
nanda
1
w niektórych językach programowania (zwłaszcza w Javie) również zapobiega dziedziczeniu
dfa
9
@dfa: aby zapobiec dziedziczeniu, musisz ustawić finalpoziom klasy. Z tego powodu umieszczanie prywatnego konstruktora jest praktycznie bezużyteczne.
nanda
3
@Will: Nie, jeśli użyjesz refleksji. Zadeklarowanie konstruktorów jako prywatnych ma na celu zapobieganie tworzeniu instancji (blokowanie odbicia), ale zapobieganie tworzeniu podklas jest efektem ubocznym, a nie intencją. Odpowiednim narzędziem do tego jest zadeklarowanie klasy final. To właśnie zrobił Sun dla klasy String i rozsądny fragment API, którego nie należy rozszerzać.
BobMcGee
96

Dostarczając prywatnego konstruktora zapobiegasz tworzeniu instancji klas w innym miejscu niż ta sama klasa. Istnieje kilka przypadków użycia takich konstruktorów.

A. Instancje klasy są tworzone w staticmetodzie. staticMetoda jest następnie uznany jako public.

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

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

B. Twoja klasa to singleton . Oznacza to, że w programie nie istnieje więcej niż jedna instancja Twojej klasy.

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

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

C. (Dotyczy tylko nadchodzącego standardu C ++ 0x) Masz kilka konstruktorów. Niektóre z nich są zadeklarowane public, inne private. Aby zmniejszyć rozmiar kodu, konstruktorzy publiczni „wywołują” konstruktory prywatne, które z kolei wykonują całą pracę. Twoje publickonstruktory są więc nazywane konstruktorami delegującymi :

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

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

D. Chcesz ograniczyć kopiowanie obiektów (na przykład z powodu korzystania z udostępnionego zasobu):

class MyClass
{
  SharedResource * myResource;

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

E. Twoja klasa jest klasą użytkową . Oznacza to, że zawiera tylko staticczłonków. W takim przypadku w programie nie wolno nigdy tworzyć instancji obiektu.

Kerido
źródło
3
W większości przypadków chciałbyś zapobiec kopiowaniu obiektów. Więc nie zapewniasz implementacji dla prywatnego konstruktora kopiującego.
frast
z przewodnika stylów google c ++ (inny przykład nie na liście, ale wspólny) -> jeśli musisz wykonać pracę w konstruktorze "rozważ funkcję fabryczną [i uczyń konstruktor prywatnym]" (tekst w nawiasach kwadratowych jest napisany przeze mnie )
Trevor Boyd Smith,
12

Pozostawić „tylne drzwi”, które pozwalają innej klasie / funkcji znajomego na skonstruowanie obiektu w sposób zabroniony użytkownikowi. Przykładem, który przychodzi na myśl, byłby kontener konstruujący iterator (C ++):

Iterator Container::begin() { return Iterator(this->beginPtr_); }
// Iterator(pointer_type p) constructor is private,
//     and Container is a friend of Iterator.
Emile Cormier
źródło
Czy to wystarczająco się różni, Terry? ;)
Emile Cormier
Dobra odpowiedź. Dlaczego nie wspomnieć o refleksji, skoro jest to jedyna droga do osiągnięcia czegoś, czego użytkownik nie może?
BobMcGee
@Bob: Musisz mnie oświecić na ten temat, ponieważ jestem głównie facetem C ++, a refleksja nie jest tak naprawdę w słowniku C ++. ;)
Emile Cormier
3
Nikt tego nie przeczyta, ale oto idzie: kilka razy zostałem odrzucony w tej sprawie. Nie zdenerwowany ani nic, ale (ze względu na naukę) chciałbym wiedzieć, dlaczego to jest złe? Jak inaczej można by skonstruować iterator z danymi potrzebnymi do uzyskania dostępu do danych kontenera?
Emile Cormier
2
@EmileCormier, myślę, że zostałeś niesprawiedliwie odrzucony, ponieważ ludzie uczący się C ++ są ciągle powtarzani: „Unikaj deklaracji znajomych”. Ta rada wydaje się być skierowana do niedoświadczonych programistów C ++, którzy w przeciwnym razie mogliby używać friendtego, gdy nie jest to uzasadnione - i jest wiele przypadków, w których jest to zły pomysł. Niestety, wiadomość została zbyt dobrze przyjęta i wielu programistów nigdy nie uczy się języka na tyle dobrze, aby zrozumieć, że sporadyczne używanie friendjest nie tylko dopuszczalne, ale i preferowane . Twój przykład był właśnie takim przypadkiem. Celowe silne połączenie nie jest przestępstwem, to decyzja projektowa.
evadeflow
10

Każdy utknął w sprawie Singletona, wow.

Inne rzeczy:

  • Powstrzymaj ludzi przed tworzeniem twojej klasy na stosie; tworzyć prywatnych konstruktorów i przekazywać wskaźniki tylko za pomocą metody fabrycznej.
  • Zapobieganie tworzeniu kopii klasy (prywatny konstruktor kopiujący)
Terry Mahaffey
źródło
8

Może to być bardzo przydatne w przypadku konstruktora, który zawiera wspólny kod; konstruktory prywatne mogą być wywoływane przez inne konstruktory przy użyciu opcji „this (...);” notacja. Tworząc wspólny kod inicjujący w konstruktorze prywatnym (lub chronionym), wyraźnie dajesz również do zrozumienia, że ​​jest on wywoływany tylko podczas konstrukcji, co nie jest tak, gdyby była po prostu metodą:

public class Point {
   public Point() {
     this(0,0); // call common constructor
   }
   private Point(int x,int y) {
     m_x = x; m_y = y;
   }
};
Będzie
źródło
3

W niektórych przypadkach możesz nie chcieć używać konstruktora publicznego; na przykład, jeśli chcesz klasę singleton.

Jeśli piszesz zestaw używany przez strony trzecie, może istnieć kilka klas wewnętrznych, które chcesz utworzyć tylko przez swój zestaw, a nie mają być tworzone przez użytkowników zestawu.

Kane
źródło
3

Gwarantuje to, że Ty (klasa z prywatnym konstruktorem) kontrolujesz sposób wywoływania konstruktora.

Przykład: statyczna metoda fabryczna klasy może zwracać obiekty, gdy metoda fabryki zdecyduje się je przydzielić (na przykład pojedyncza fabryka).

Preet Sangha
źródło
@Skilldrick: jednym z przykładów jest to, że możesz wymusić przydzielenie klasy tylko do sterty.
Dirk
@dirk Usunąłem swój komentarz, ponieważ nie jest już aktualny.
Skilldrick,
3

Możemy też mieć prywatnego konstruktora, który umożliwi stworzenie obiektu tylko przez określoną klasę (ze względów bezpieczeństwa).

Jednym ze sposobów jest zorganizowanie zajęć z przyjaciółmi.

Przykład w 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.
     }
};

Uwaga: Uwaga: tylko ClientClass (ponieważ jest przyjacielem SecureClass) może wywoływać Konstruktora SecureClass.

vijayNidumolu
źródło
2

jeśli nie chcesz, aby użytkownicy tworzyli instancje tej klasy lub tworzyli klasę, która dziedziczy tę klasę, jak np. java.lang.math, cała funkcja w tym pakiecie jest static, wszystkie funkcje można wywołać bez tworzenia instancji math, więc konstruktor jest ogłaszany jako statyczny .

shinxg
źródło
1

Jeśli jest prywatny, nie możesz go nazwać ==> nie możesz utworzyć instancji klasy. Przydatne w niektórych przypadkach, na przykład singleton.

Jest dyskusja i kilka przykładów tutaj .

Seth
źródło
1

Widziałem Twoje pytanie dotyczące tego samego problemu.

Po prostu, jeśli nie chcesz pozwalać innym na tworzenie instancji, trzymaj konstruktor w ograniczonym zakresie. Praktyczne zastosowanie (przykład) to wzorzec singleton.

Chathuranga Chandrasekara
źródło
1

Nie powinieneś ustawiać konstruktora jako prywatnego. Kropka. Zadbaj o ochronę, aby w razie potrzeby przedłużyć klasę.

Edycja: Stoję przy tym, bez względu na to, ile głosów przeciw temu rzucisz. Odcinasz potencjał przyszłego rozwoju kodu. Jeśli inni użytkownicy lub programiści są naprawdę zdeterminowani, aby rozszerzyć klasę, po prostu zmienią konstruktor na chroniony w kodzie źródłowym lub bajtowym. Nie osiągniesz nic poza tym, że ich życie będzie trochę trudniejsze. Dołącz ostrzeżenie w komentarzach konstruktora i tak to zostaw.

Jeśli jest to klasa użytkowa, prostszym, poprawniejszym i bardziej eleganckim rozwiązaniem jest oznaczenie całej klasy „statycznym końcem”, aby zapobiec rozszerzaniu. Samo oznaczenie konstruktora jako prywatnego nie przyniesie nic dobrego; naprawdę zdeterminowany użytkownik może zawsze użyć refleksji, aby uzyskać konstruktora.

Prawidłowe zastosowania:

  • Jedno dobre użycie protected konstruktora jest wymuszenie użycia statycznych metod fabryki, które pozwalają na ograniczenie tworzenia instancji lub puli i ponownego wykorzystania kosztownych zasobów (połączenia z bazą danych, zasoby natywne).
  • Singletony (zwykle nie jest to dobra praktyka, ale czasami jest to konieczne)
BobMcGee
źródło
2
Z mojego doświadczenia wynika, że ​​nie ma prawd absolutnych, nawet goto może być użyte, jeśli sytuacja tego wymaga. Istnieją złe i złe sposoby, ale jak to ujął Marshall Cline, czasami trzeba wybierać między mniejszym złem. parashift.com/c++-faq-lite/big-picture.html#faq-6.15 Jeśli chodzi o konstruktorów prywatnych, to są one potrzebne, a nawet nie są dla Ciebie złe. Oznacza to po prostu, że nikt, łącznie z twoimi podklasami, nie powinien go używać.
daramarak
Gotos mają swoje miejsce, to prawda, ale oznaczenie konstruktora jako prywatnego nie przynosi nic poza kłopotami na drodze. Zredagowałem swój post, aby dokładniej wyjaśnić, dlaczego.
BobMcGee
Kopiowanie konstrukcji lub domyślnej konstrukcji niektórych klas nie ma sensu . W C ++ można to wskazać, deklarując prywatny ctor bez definiowania go (co jest również wspólne dla operatora =).
Optymalizacja kompilatorów, takich jak Java JIT i GWT, faktycznie korzysta z prywatnych konstruktorów: w celu ograniczenia zakresu instancji i lepszej pracy przy wstawianiu / przycinaniu kodu.
Ajax
1

Konstruktor jest prywatny w niektórych celach, na przykład gdy trzeba zaimplementować singleton lub ograniczyć liczbę obiektów klasy. Na przykład w implementacji singletona musimy ustawić konstruktor jako prywatny

#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();
}

Ponownie, jeśli chcesz ograniczyć tworzenie obiektu do 10, użyj następującego

#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

}

Dzięki

Tunvir Rahman Tusher
źródło
1

Możesz mieć więcej niż jednego konstruktora. C ++ udostępnia domyślny konstruktor i domyślny konstruktor kopiujący, jeśli nie podasz go jawnie. Załóżmy, że masz klasę, którą można zbudować tylko przy użyciu sparametryzowanego konstruktora. Może zainicjował zmienne. Jeśli użytkownik użyje tej klasy bez tego konstruktora, może to spowodować niekończące się problemy. Dobra zasada ogólna: jeśli domyślna implementacja jest nieprawidłowa, ustaw konstruktor domyślny i kopiujący jako prywatne i nie podawaj implementacji:

class C
{
public:
    C(int x);

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

Użyj kompilatora, aby uniemożliwić użytkownikom używanie obiektu z domyślnymi konstruktorami, które są nieprawidłowe.

Charles
źródło
2
W przypadku podania konstruktora innego niż domyślny bez określania konstruktora domyślnego domyślny konstruktor nie istnieje. Nie musisz go tworzyć i ustawiać jako prywatny.
TT_
0

Cytat z Effective Java , możesz mieć klasę z prywatnym konstruktorem, aby mieć klasę narzędziową, która definiuje stałe (jako statyczne pola końcowe).

( EDYTUJ: zgodnie z komentarzem jest to coś, co może mieć zastosowanie tylko w Javie, nie wiem, czy ta konstrukcja ma zastosowanie / jest potrzebna w innych językach OO (powiedzmy C ++))

Przykład jak poniżej:

public class Constants {
    private Contants():

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

EDIT_1 : Ponownie, poniższe wyjaśnienie ma zastosowanie w Javie: (i na podstawie książki Effective Java )

Instancja klasy użytkowej takiej jak ta poniżej, choć nie jest szkodliwa, nie służy żadnemu celowi, ponieważ nie została zaprojektowana do tworzenia instancji.

Na przykład załóżmy, że nie ma prywatnego konstruktora dla stałych klasy. Fragment kodu jak poniżej jest prawidłowy, ale nie lepiej oddaje intencji użytkownika klasy Constants

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

w przeciwieństwie do kodu takiego jak

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

Myślę też, że prywatny konstruktor lepiej oddaje intencje projektanta klasy Constants (powiedzmy).

Java udostępnia domyślny konstruktor publiczny bez parametrów, jeśli nie jest dostarczony żaden konstruktor, a jeśli zamierzasz zapobiec tworzeniu instancji, potrzebny jest konstruktor prywatny.

Nie można oznaczyć jako statycznej klasy najwyższego poziomu, a nawet można utworzyć instancję klasy końcowej.

sateesh
źródło
2
Ale w C ++ nie potrzebujesz do tego klasy. Jeśli coś nie zależy od danych wewnątrz obiektu, zapisz to jako wolne funkcje i wolne zmienne. Chcesz hermetyzacji? Użyj przestrzeni nazw.
daramarak
@daramarak: dzięki, nie mam doświadczenia z C ++. Zaktualizowałem odpowiedź, aby odzwierciedlić, że ma to zastosowanie tylko w Javie
sateesh
2
Jeśli twój obiekt po prostu hermetyzuje zmienne statyczne, po co ograniczać tworzenie instancji? Po co określać cokolwiek o konstruktorze? Nie zaszkodzi, jeśli zostanie utworzony. Wygląda na to, że podobne wyniki można uzyskać, deklarując klasę jako statyczną i ostateczną.
BobMcGee
@BobMcGee, dziękuję za komentarz. To zmusiło mnie do zastanowienia się (i odniesienia) do tego, co opublikowałem. Zredagowałem moją odpowiedź, aby dodać więcej powodów dotyczących użyteczności prywatnego konstruktora.
sateesh
0

Klasy narzędziowe mogą mieć prywatnych konstruktorów. Użytkownicy klas nie powinni mieć możliwości tworzenia instancji tych klas:

public final class UtilityClass {
    private UtilityClass() {}

    public static utilityMethod1() {
        ...
    }
}
gpampara
źródło
1
Dlaczego ma znaczenie, czy tworzona jest instancja klasy narzędziowej? Wszystko, co robi, to utworzenie obiektu bez pól i zjadanie kilku bajtów pamięci.
BobMcGee
Możliwość utworzenia instancji tworzy niejednoznaczny interfejs API. Jeśli projektujesz klasę jako klasę użytkową bez stanu i chcesz ją tak zachować. Możesz podklasować klasę za pomocą publicznego konstruktora. Podklasa niektórych metod użytkowych jest idiotyczna.
gpampara
@BobMcGee: oczywiście zaprojektowanie klasy, która działa i zaprojektowanie klasy, która będzie używana przez innych ludzi, to różne rzeczy. Ci, którzy pracują nad rozwojem API (tacy jak ludzie Sun lub koleś od Google) zabiją każdego, kto będzie próbował powiedzieć, że prywatny konstruktor w klasie użytkowej jest bezużyteczny.
nanda
@gpampara: Deklarowanie klasy jako ostatecznej zapobiega tworzeniu podklas. To właśnie zrobił Sun dla klasy String. @Nanda: Klasa narzędziowa nie potrzebuje zdefiniowanego konstruktora. Jeśli nie chcesz, aby był rozszerzalny, zadeklaruj, że nie jest, używając „final”.
BobMcGee
1
@BobMcGee: Wygląda na to, że uwielbiasz oglądać przykład autorstwa Sun. Następnie sprawdź kolekcje klas narzędziowych z Sun: docjar.com/html/api/java/util/Collections.java.html . Rzeczywiście używa prywatnego konstruktora.
nanda
0

Możesz chcieć uniemożliwić swobodne tworzenie instancji klasy. Zobacz wzorzec projektowania singleton jako przykład. Aby zagwarantować wyjątkowość, nie możesz pozwolić nikomu stworzyć jej instancji :-)

Seb
źródło
0

Jednym z ważnych zastosowań jest klasa 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
   }
};

Jest również odpowiedni, jeśli twoja klasa ma tylko metody statyczne. tj. nikt nie musi tworzyć instancji Twojej klasy

SysAdmin
źródło
Należy zauważyć, że singleton jest przez wielu uważany za „anty-wzorzec” i nie należy lekceważyć decyzji o jego zastosowaniu. Powszechną alternatywą jest wstrzykiwanie zależności.
Michael Aaron Safyan
SingleTon nie jest anty-wzorcem. Jednak nadużywanie wzoru (z powodu braku wiedzy o jego zastosowaniu) nie jest dobre. Należy zauważyć, że jest to jeden z wzorców GOF.
SysAdmin
0

To naprawdę jeden oczywisty powód: chcesz zbudować obiekt, ale nie jest to praktyczne (jeśli chodzi o interfejs) w konstruktorze.

FactoryPrzykładem jest dość oczywiste, pozwól mi zademonstrować Named Constructoridiom.

Powiedzmy, że mam klasę, Complexktóra może reprezentować liczbę zespoloną.

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

Pytanie brzmi: czy konstruktor oczekuje części rzeczywistej i urojonej, czy też oczekuje normy i kąta (współrzędne biegunowe)?

Mogę zmienić interfejs, żeby było łatwiej:

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

Nazywa się to Named Constructoridiomem: klasę można zbudować tylko od zera, jawnie podając, którego konstruktora chcemy użyć.

To szczególny przypadek wielu metod konstrukcyjnych. Wzorce projektowe zapewniają dużą liczbę sposobów budowania obiektu: Builder, Factory, Abstract Factory, ... i prywatny konstruktor będzie upewnić się, że użytkownik jest odpowiednio ograniczany.

Matthieu M.
źródło
0

Oprócz bardziej znanych zastosowań…

Aby zaimplementować wzorzec Method Object , który podsumowałbym jako:

„Prywatny konstruktor, publiczna metoda statyczna”
„Obiekt do implementacji, funkcja interfejsu”

Jeśli chcesz zaimplementować funkcję za pomocą obiektu, a obiekt nie jest przydatny poza wykonaniem jednorazowych obliczeń (przez wywołanie metody), masz obiekt Throwaway . Możesz hermetyzować tworzenie obiektu i wywołanie metody w metodzie statycznej, zapobiegając temu typowemu anty-wzorcowi:

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

… Zastępując go wywołaniem funkcji (z przestrzenią nazw):

z = A.f(x,y);

Wzywający nigdy nie musi wiedzieć ani dbać o to, że używasz obiektu wewnętrznie, uzyskując bardziej przejrzysty interfejs i zapobiegając śmieciom z obiektu wiszącego w pobliżu lub nieprawidłowego użycia obiektu.

Na przykład, jeśli chcesz, aby rozbić obliczenia całej metody foo, bari zork, na przykład do stanu zakładowego bez konieczności przechodzenia wiele wartości i wyjść z funkcji, można go realizować w następujący sposób:

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) { /* ... */ };
}

Ten wzorzec Method Object jest podany w Smalltalk Best Practice Patterns , Kent Beck, strony 34–37, gdzie jest ostatnim krokiem wzorca refaktoryzacji, kończącym się:

  1. Zastąp oryginalną metodę taką, która tworzy wystąpienie nowej klasy, skonstruowaną z parametrami i odbiornikiem oryginalnej metody i wywołuje „compute”.

Różni się to znacznie od innych przykładów tutaj: klasa jest instancyjna (w przeciwieństwie do klasy użytkowej), ale instancje są prywatne (w przeciwieństwie do metod fabrycznych, w tym singletonów itp.) I mogą żyć na stosie, ponieważ nigdy nie uciekają.

Ten wzorzec jest bardzo przydatny w OOP od dołu do góry, gdzie obiekty są używane do uproszczenia implementacji niskiego poziomu, ale niekoniecznie są ujawniane zewnętrznie i kontrastuje z odgórnym OOP, które jest często prezentowane i zaczyna się od interfejsów wysokiego poziomu.

Nils von Barth
źródło
0

Czasami jest to przydatne, jeśli chcesz kontrolować, jak i kiedy (i ile) instancji obiektu jest tworzonych.

Między innymi stosowane we wzorach:

Singleton pattern
Builder pattern
ssedano
źródło
W jaki sposób prywatny konstruktor jest przydatny w niezmiennym obiekcie? Niezmienność polega na zapobieganiu zmianom obiektu po utworzeniu , podczas gdy prywatne konstruktory mają na celu zapobieganie tworzeniu .
Nils von Barth
0

Korzystanie z prywatnych konstruktorów może również zwiększyć czytelność / łatwość konserwacji w obliczu projektowania opartego na domenie. Z „Microsoft .NET - Aplikacje do projektowania architektury dla przedsiębiorstw, wydanie 2”:

var request = new OrderRequest(1234);

Cytuj: „Występują tu dwa problemy. Po pierwsze, patrząc na kod, trudno zgadnąć, co się dzieje. Tworzona jest instancja OrderRequest, ale dlaczego i przy użyciu jakich danych? Co to jest 1234? Prowadzi to do drugiego problemu: naruszasz wszechobecny język ograniczonego kontekstu. Język prawdopodobnie mówi mniej więcej tak: klient może złożyć żądanie zamówienia i może podać identyfikator zakupu. W takim przypadku jest lepszy sposób na uzyskanie nowej instancji OrderRequest : "

var request = OrderRequest.CreateForCustomer(1234);

gdzie

private OrderRequest() { ... }

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

Nie zalecam tego dla każdej klasy, ale dla powyższego scenariusza DDD myślę, że ma sens zapobieganie bezpośredniemu tworzeniu nowego obiektu.

Morten Nørgaard
źródło