Τι είναι το DI Container;
Το Dependency injection container (DIC) είναι μια κλάση που μπορεί να ενσαρκώνει και να διαμορφώνει αντικείμενα.
Μπορεί να σας εκπλήξει, αλλά σε πολλές περιπτώσεις δεν χρειάζεστε ένα dependency injection container για να εκμεταλλευτείτε το dependency injection (DI για συντομία). Εξάλλου, ακόμη και σε προηγούμενο κεφάλαιο δείξαμε συγκεκριμένα παραδείγματα DI και δεν χρειαζόταν κανένας περιέκτης.
Ωστόσο, αν πρέπει να διαχειριστείτε έναν μεγάλο αριθμό διαφορετικών αντικειμένων με πολλές εξαρτήσεις, ένας περιέκτης dependency injection θα είναι πραγματικά χρήσιμος. Κάτι που ίσως ισχύει για εφαρμογές ιστού που είναι χτισμένες σε ένα πλαίσιο.
Στο προηγούμενο κεφάλαιο, παρουσιάσαμε τις κλάσεις Article
και
UserController
. Και οι δύο έχουν κάποιες εξαρτήσεις, δηλαδή τη βάση
δεδομένων και το εργοστάσιο ArticleFactory
. Και για αυτές τις κλάσεις,
θα δημιουργήσουμε τώρα έναν περιέκτη. Φυσικά, για ένα τόσο απλό
παράδειγμα, δεν έχει νόημα να έχουμε ένα δοχείο. Αλλά θα δημιουργήσουμε
έναν για να δείξουμε πώς φαίνεται και πώς λειτουργεί.
Εδώ είναι ένας απλός σκληρά κωδικοποιημένος περιέκτης για το παραπάνω παράδειγμα:
Η χρήση θα έμοιαζε ως εξής:
Το δοχείο τα γνωρίζει όλα αυτά. Οι εξαρτήσεις εγχέονται αυτόματα από τον περιέκτη. Αυτή είναι η δύναμή του.
Μέχρι στιγμής, ο περιέκτης έχει τα πάντα κωδικοποιημένα. Οπότε κάνουμε το επόμενο βήμα και προσθέτουμε παραμέτρους για να κάνουμε τον περιέκτη πραγματικά χρήσιμο:
Οι έξυπνοι αναγνώστες μπορεί να έχουν παρατηρήσει ένα πρόβλημα. Κάθε
φορά που παίρνω ένα αντικείμενο UserController
, δημιουργείται επίσης
μια νέα περίπτωση ArticleFactory
και μια νέα βάση δεδομένων. Σίγουρα
δεν το θέλουμε αυτό.
Έτσι προσθέτουμε μια μέθοδο getService()
που θα επιστρέφει τα ίδια
instances ξανά και ξανά:
Η πρώτη κλήση π.χ. της $container->getService('Database')
θα έχει ως
αποτέλεσμα η createDatabase()
να δημιουργήσει ένα αντικείμενο βάσης
δεδομένων, το οποίο θα αποθηκεύσει στον πίνακα $services
και θα το
επιστρέψει άμεσα στην επόμενη κλήση.
Τροποποιούμε επίσης το υπόλοιπο δοχείο ώστε να χρησιμοποιεί το
getService()
:
Παρεμπιπτόντως, ο όρος service αναφέρεται σε κάθε αντικείμενο που
διαχειρίζεται ο περιέκτης. Εξ ου και το όνομα της μεθόδου
getService()
.
Έγινε. Έχουμε ένα πλήρως λειτουργικό DI container! Και μπορούμε να το χρησιμοποιήσουμε:
Όπως μπορείτε να δείτε, δεν είναι δύσκολο να γράψετε ένα DIC. Είναι αξιοσημείωτο ότι τα ίδια τα αντικείμενα δεν γνωρίζουν ότι ένα δοχείο τα δημιουργεί. Έτσι, είναι δυνατόν να δημιουργηθεί οποιοδήποτε αντικείμενο στην PHP με αυτόν τον τρόπο χωρίς να επηρεαστεί ο πηγαίος κώδικάς τους.
Η χειροκίνητη δημιουργία και συντήρηση μιας κλάσης εμπορευματοκιβωτίου μπορεί να γίνει ένας εφιάλτης μάλλον γρήγορα. Επομένως, στο επόμενο κεφάλαιο θα μιλήσουμε για το Nette DI Container, το οποίο μπορεί να δημιουργεί και να ενημερώνεται σχεδόν αυτόματα.