Ένταση εξάρτησης από τον εντοπιστή υπηρεσίας

Φωτογραφία από τον John Carlisle στο Unsplash

Πολλοί προγραμματιστές εκεί έξω δεν βλέπουν τη διαφορά μεταξύ της ένεσης εξάρτησης και των σχεδίων σχεδιασμού εντοπισμού υπηρεσιών. Ναι, και οι δύο προσπαθούν να λύσουν το ίδιο πρόβλημα - να αυξήσουν την αποσύνδεση. Όλοι γνωρίζουμε ποια οφέλη μας προσφέρουν όταν πρόκειται για κλιμάκωση, έλεγχο ή απλά ανάγνωση του κώδικα.

Ωστόσο, πώς μπορώ να μάθω πότε να χρησιμοποιήσω ένεση εξάρτησης και πότε να χρησιμοποιήσω τον εντοπισμό υπηρεσίας; Θα έλεγα ότι θα πρέπει να χρησιμοποιήσουμε και τα δύο, όταν χρειάζεται.

Εάν μου ζητηθεί να επιλέξω ένα μόνο ρήμα που περιγράφει καλύτερα το μοτίβο εγχύσεων εξάρτησης θα επέλεγα "να δώσω". Αν το σκεφτείτε, αυτό ακριβώς επιτυγχάνουμε με την ένεση εξάρτησης τελικά. Απλά δίνουμε αντικείμενα σε ένα αντικείμενο.

$ window = νέο παράθυρο ();
$ πόρτα = νέα πόρτα ();
$ house = νέο σπίτι ($ παράθυρο, $ πόρτα);

Σε αυτή την περίπτωση, δίνουμε το αντικείμενο του παραθύρου και το αντικείμενο της πόρτας στο αντικείμενο του σπιτιού.

Από την άλλη πλευρά, αν μου ζητηθεί να περιγράψω το μοτίβο εντοπισμού υπηρεσίας με ένα μόνο ρήμα θα έλεγα "να πάρω". Απλά σκέψου το. Αυτό κάνουμε όταν χρησιμοποιούμε έναν εντοπιστή υπηρεσίας. Παίρνουμε αντικείμενα από ένα αντικείμενο.

$ house = $ serviceLocator-> get (Σπίτι :: τάξη);

Όπως μπορείτε να δείτε, παίρνουμε το αντικείμενο του σπιτιού από τον εντοπιστή υπηρεσιών.

Σε πολλές περιπτώσεις, η ένεση εξάρτησης και ο εντοπιστής υπηρεσίας λειτουργούν ως ενιαία μονάδα. Μπορεί να μην το δούμε όταν τα πράγματα εγχέονται αυτομάτως αλλά πίσω από τη σκηνή οι υλοποιήσεις της έγχυσης εξάρτησης βασίζονται σε εντοπιστές υπηρεσιών για να ανακτήσουν τις πραγματικές εξαρτήσεις.

Έτσι μπορεί να φαίνεται κάπου στον κώδικα:

foreach (εξαρτήσεις $ ως εξάρτηση $) {
    $ περιπτώσεις [] = $ this-> container-> get ($ εξάρτηση);
}}
επιστρέψτε $ this-> resolve ($ class, $ instances);

Ένας εντοπιστής υπηρεσιών είναι αρκετά εύκολο να εφαρμοστεί. Το μόνο που χρειάζεστε είναι να έχετε τη δυνατότητα να αποκτήσετε ένα απαιτούμενο στιγμιότυπο με όνομα ή αναγνωριστικό και την ικανότητα να ελέγξετε αν πράγματι υπάρχει η απαιτούμενη παρουσία. Αξίζει να σημειωθεί ότι ένας εντοπιστής υπηρεσίας συχνά ονομάζεται δοχείο. Και τα δύο πράγματα είναι τα ίδια. Και οι δύο προορίζονται να παρέχουν στιγμιότυπα ή υπηρεσίες, ωστόσο προτιμάτε να τους καλέσετε. Φυσικά, υπάρχει μια διαφορά μεταξύ μιας υπηρεσίας και ενός στιγμιότυπου όταν μιλάμε για όρους και σκοπούς, αλλά από τεχνική άποψη είναι όλες οι περιπτώσεις ορισμένων τάξεων.

Ακολουθεί μια πρωτότυπη έκδοση του εντοπιστή υπηρεσίας (γνωστός ως κοντέινερ):

class ServiceLocator {

    ιδιωτικές $ υπηρεσίες = [];

    Δημόσια συνάρτηση get (string $ id):? αντικείμενο {
        επιστρέψτε $ this-> υπηρεσίες [$ id] ?? μηδενικό;
    }}


    Δημόσια συνάρτηση έχει (συμβολοσειρά $ id): bool {
        ($ this-> services [$ id]);
    }}

    δημόσιο μητρώο λειτουργιών (string $ id, αντικείμενο $ service): void {
        $ this-> υπηρεσίες [$ id] = $ υπηρεσία;
    }}
}}
$ serviceLocator = νέο ServiceLocator ();
$ serviceLocator-> register ('house', νέο σπίτι));
// κάπου αλλού

αν ($ serviceLocator-> έχει ('house')) {
    $ house = $ serviceLocator-> get ('σπίτι');
}}

Επιπλέον, έχω δώσει τον τρόπο για την καταχώρηση των υπηρεσιών.

Οι εφαρμογές της έγχυσης εξαρτήσεων συνήθως εισάγουν εξαρτήσεις σε αντικείμενα αυτόματα. Το μόνο που χρειάζεστε είναι να δώσετε λίγο διαμόρφωση και αυτό είναι όλο. Αυτό είναι αρκετά βολικό σε πολλές περιπτώσεις, αλλά υπάρχουν περιπτώσεις που πρέπει να χρησιμοποιήσετε τον εντοπιστή υπηρεσιών για να αποφύγετε το αδιέξοδο. Αυτό θα μπορούσε να συμβεί όταν δύο περιπτώσεις εξαρτώνται το ένα από το άλλο μέσω κατασκευαστή. Ακολουθεί ένα παράδειγμα:

τάξη Α {
    
    δημόσια λειτουργία __construct (B $ b)
    {
        //
    }}
}}

κατηγορία Β {
    δημόσια λειτουργία __construct (A $ a)
    {
        //
    }}
}}
$ a = νέο Α (...); // Χρειαζόμαστε B!
$ b = νέα B (...); // Χρειαζόμαστε ενα!

Όπως μπορείτε να δείτε, δεν μπορούμε να επιλύσουμε καμία από τις υπηρεσίες επειδή εξαρτώνται από το ένα το άλλο. Δεν μπορούμε να επιλύσουμε την υπηρεσία Α επειδή απαιτεί την υπηρεσία Β και δεν μπορούμε να επιλύσουμε την υπηρεσία Β επειδή απαιτεί την υπηρεσία Α. Για να το λύσουμε αυτό, πρέπει να ανακτήσουμε μία από τις υπηρεσίες σε τεμπέλης φόρτωσης. Αυτό σημαίνει ότι πρέπει να λάβουμε μία από τις υπηρεσίες από τον εντοπιστή υπηρεσίας στο σημείο που απαιτείται η υπηρεσία και όχι στον κατασκευαστή.

Ολα για όλα

Ελπίζω ότι αυτό το άρθρο εκκαθάρισε μερικά πράγματα για εσάς και σας άρεσε να το διαβάσετε. Αν όχι, τότε πρέπει να είσαι ήδη πιο έξυπνος προγραμματιστής εκεί έξω ;-)