Il costruttore dovrebbe fare solo una cosa e farlo bene: costruisci l'oggetto (qui un'istanza di Server
).
No, non fare tutto questo nel costruttore! Ecco perché
Se aggiungi altre cose, come creare un socket e associarlo a un indirizzo di porta, dovrai affrontare diversi problemi. Ad esempio:
- Cosa succede se il binding della porta è andato storto: il costruttore non dovrebbe funzionare? O dovrebbe restituire l'istanza, ma in uno stato di errore che potrebbe consentire il successivo recupero?
- E se ci fossero alternative diverse per fare la stessa cosa, ad esempio legare il server a una porta IPv4 o associare il server a un indirizzo IPv6?
Inoltre, se il costruttore avvia operazioni che non terminano, come ascoltare e gestire le richieste dei client, tutto il codice verrà eseguito su un oggetto non finito (vale a dire prima che il costruttore sia completato).
Infine, alcune lingue non consentono di derivare in modo efficace un nuovo tipo ServerXXX
, e sovrascrivono alcuni dei suoi metodi. Ad esempio, in C ++, il costruttore Server
verrà eseguito sull'oggetto di base Server
di ServerXXX
e non sarà a conoscenza dei metodi ServerXXX
sottoposti a override. Solo una volta che il costruttore Server
sarà finito, passerà al costruttore ServerXXX
Come si fa meglio?
Ci sono diverse alternative. Non conoscendo tutti i dettagli, potrei immaginare di utilizzare un modello di builder (GoF) :
- Un costruttore astratto definirà l'interfaccia generale per costruire il server, costruendo le diverse parti necessarie.
- Un costruttore concreto implementerà questa interfaccia per una determinata classe Server e fornirà la colla per assemblare le parti.
- Un "client" crea il builder concreto appropriato e lo inserisce nel director
- Un direttore invocerebbe i metodi del contraffattore controcorrente nell'ordine appropriato
- Il client invoca il builder concreto per ottenere il server finale pronto per l'uso.
Questo tipo di approccio non è l'ideale per eseguire affari correnti, vale a dire ascoltare e gestire la richiesta. Questo non è sicuramente parte del processo di costruzione. Inoltre, questo potrebbe richiedere il multithreading, un thread che fa l'ascolto e molti altri thread che gestiscono le richieste per i client connessi.
Per questa parte, suggerisco di utilizzare il modello di metodo del modello che implementa l'evento loop per il server. Il codice principale sarebbe quindi qualcosa del tipo:
ServerBuilder builder;
ServerDirector director(builder);
director.construct(); // creates the server and its components
Server server = director.get_result(); // server ready to use
server.mainloop();