2017-10-03 11 views
6

का उपयोग करके लैरावेल सोलीड मैं सोलिड सिद्धांतों का पालन करने के लिए (इस पल में) चाहता हूं, लेकिन मेरा दिमाग उड़ाएगा।रेस्पोजिटरी पैटर्न

मैंने रिपोर्टर पैटर्न को लारवेल में सोलिड सिद्धांतों का पालन करने के लिए बहुत सी पोस्ट पढ़ीं। मेरा प्रश्न this question के समान है। लेकिन मुझे समझ नहीं आता कि कैसे मैं फैक्टरी पैटर्न

मैं एक दो फैक्टर प्रमाणीकरण प्रणाली विकसित कर रहा हूँ में खुला/बंद प्रधान का उल्लंघन नहीं करते कर सकते हैं और मैं TFA के रूप में उपयोग करने के लिए कई तरीके होते है।

अब अधिकार:

  • प्रमाणक ऐप्स
  • एसएमएस

कोड के लिए आइए कूद:

नियंत्रक: (कारखाने के बिना)

public function index(Request $request) 
{ 
    // Violate the OCP. I'm modyfing the class. 
    switch ($request->method) { 
     case 'authenticator': 
      $tfaMethod = new Authenticator; 
      break; 
     case 'sms': 
      $tfaMethod = new SMS; 
      break; 
    } 

    return (new TwoFactorMethod)->process($this->currentUser, $tfaMethod); 
} 

TwoFactorMethod वर्ग:

public function process($user, MethodInterface $method) 
{ 
    return $method->process($user); 
} 

प्रत्येक विधि अपने ही वर्ग है। यह ठीक है। लेकिन अगर मैं एक नई विधि जोड़ना चाहता हूं, जैसे: ई-मेल मैं स्विच केस का उपयोग कर कक्षा में ओसीपी तोड़ दूंगा।

मैं "ठीक" कैसे कर सकता हूं? या सिर्फ मेरी तरफ से एक गलतफहमी है?

धन्यवाद!

+0

आप लार्वेल के सेवा कंटेनर का उपयोग कर सकते हैं। उदाहरण के लिए बाध्यकारी बनाएं 'ऐप() -> बाइंड (" tfa.authenticator ", प्रमाणीकरणकर्ता :: वर्ग)' और 'ऐप() -> बाइंड (" tfa.sms ", एसएमएस :: कक्षा) 'और फिर आप सही एक प्राप्त कर सकते हैं 'ऐप() -> बनाना (" tfa। "। $ request-> विधि) 'स्विच करने की आवश्यकता के बिना, जब आप अधिक विधियों का समर्थन करते हैं तो बस बाइंडिंग जोड़ें (और अगर आप कंटेनर से शून्य हो जाते हैं तो विफल हो जाते हैं)। या क्या मैं आपको गलत समझ रहा हूँ? – apokryfos

उत्तर

5

आप एक TfaMethodRegisty, हो सकता है कुछ इस तरह इस्तेमाल कर सकते हैं:

class TfaMethodRegistry 
{ 
    protected $methods = []; 


    public function register($name, $class) 
    { 
     $this->methods[$name] = $class; 
    } 


    public function get($name) 
    { 
     return $this->methods[$name]; 
    } 
} 

तो फिर आप अपने AppServiceProvider में उदाहरण के लिए पॉप्युलेट:

public function register() 
{ 
    $this->app->bind('App\TfaMethodRegistry', function ($app) { 
     $registry new TfaMethodRegistry; 

     $registry->register('sms', new Sms); 
     $registry->register('authenticator', new Authenticator); 

     return $registry; 
    }); 
} 

और फिर तुम सिर्फ कर सकते हैं Laravel आईओसी कंटेनर अपने नियंत्रक में इंजेक्ट करें या जहां भी आपको इसकी आवश्यकता हो:

public function index(Request $request, TfaMethodRegistry $registry) 
{ 
    $tfaMethod = $registry->get($request->method); 

    return (new TwoFactorMethod)->process($this->currentUser, $tfaMethod); 
} 

तो मूल रूप से आप कॉन्फ़िगरेशन के रूप में उपलब्ध विधियों का इलाज कर रहे हैं लेकिन कुछ भी संपादन किए बिना रनटाइम पर भी अधिक जोड़ सकते हैं।

बस एक छोटी सी युक्ति: इस के साथ बहुत पागल मत बनो और पूरी सोलिड-चीज को भी धार्मिक रूप से न लें। अधिकांशतः, KISS सॉलिड से बेहतर तरीका है :)

+0

वाह! कमाल दोस्त। आपका बहुत बहुत धन्यवाद! और टिप के बारे में, मुझे यह मिल गया। कभी-कभी मैं वास्तव में इसके साथ बहुत पागल हो गया। – webmasterdro

1

जब तक कि आप अन्य क्लाइंट्स द्वारा उपयोग की जाने वाली लाइब्रेरी नहीं लिख रहे हैं, मेरी सलाह यह है कि आप कारखाने को यह ज्ञान देते हैं, खासकर अगर कक्षाओं की सूची यह संरचना काफी कम और स्थैतिक है। आपको मुख्य लाभ मिलेगा: अपने शेष कोड को स्विच/केस कथन, और केंद्रीकृत ज्ञान के साथ हल करने के लिए नहीं, लेकिन बिना सिरदर्द के।

इस कैसे दिखाई दे सकते का एक उदाहरण:

class TwoFactorAuthenticatorFactory { 
    public static function createFromMethod(string $method): TwoFactorAuthenticator 
    { 
     switch ($method) { 
      case 'authenticator': 
       return new Authenticator(); 
      case 'sms': 
       return new SMS(); 
     } 

     throw new RuntimeException(sprintf('Method %s could not be resolved to an authenticator.', $method)); 
    } 
} 

उपयोग:

TwoFactorAuthenticatorFactory::createFromMethod($request->method); 

मैं आप कैसे आप इस "हठधर्मिता से", लेकिन @Quasdunk का समाधान होगा पर एक त्वरित ठहरनेवाला देने के लिए योजना बना रहा था मुझे एक उत्कृष्ट उत्तर के साथ पंच पर हराया :) ध्यान दें कि, चीजों को (संभवतः अनावश्यक रूप से) अधिक अमूर्त बनाने के अलावा, इस समाधान में डोमेन से फ्रेमवर्क इंफ्रास्ट्रक्चर परत में ज्ञान को कैसे स्थानांतरित किया गया है, इस बारे में भी बड़ी कमी है। यह आपको ढांचे पर बांध देगा, जो कि आप आम तौर पर टालना चाहते हैं।

+0

दरअसल, इस स्थिति के लिए बिल्कुल ठीक है। – pbond

+0

अच्छा समाधान भी। मैं देखता हूं कि टेलर ओटवेल इस तरह के कुछ का उपयोग करते हैं, यहां: https://medium.com/@taylorotwell/expressive-code-real-time-facades-41c442914291 – webmasterdro

संबंधित मुद्दे