एक विधि के साथ एक वर्ग के लिए उचित डिजाइन जो ग्राहकों के बीच भिन्न हो सकते हैं


12

मेरे पास ग्राहक भुगतानों को संसाधित करने के लिए उपयोग किया जाने वाला एक वर्ग है। इस वर्ग के सभी तरीकों में से एक, प्रत्येक ग्राहक के लिए एक ही है, एक को छोड़कर, जो इस बात की गणना करता है (उदाहरण के लिए) कि ग्राहक कितना बकाया है। यह ग्राहक से ग्राहक के लिए बहुत भिन्न हो सकता है और गुण फ़ाइल जैसी किसी चीज़ में गणनाओं के तर्क को पकड़ने का कोई आसान तरीका नहीं है, क्योंकि कस्टम कारकों की कोई भी संख्या हो सकती है।

मैं बदसूरत कोड लिख सकता हूं जो customerID के आधार पर स्विच करता है:

switch(customerID) {
 case 101:
  .. do calculations for customer 101
 case 102:
  .. do calculations for customer 102
 case 103:
  .. do calculations for customer 103
 etc
}

लेकिन इसके लिए हमें हर बार एक नया ग्राहक प्राप्त करने के लिए कक्षा के पुनर्निर्माण की आवश्यकता होती है। बेहतर तरीका क्या है?

[संपादित करें] "डुप्लिकेट" लेख पूरी तरह से अलग है। मैं यह नहीं पूछ रहा हूं कि स्विच स्टेटमेंट से कैसे बचा जाए , मैं इस मामले पर लागू होने वाले आधुनिक डिजाइन के लिए पूछ रहा हूं - जिसे मैं एक स्विच स्टेटमेंट के साथ हल कर सकता हूं अगर मैं डायनासोर कोड लिखना चाहता था। दिए गए उदाहरण सामान्य हैं, और सहायक नहीं हैं, क्योंकि वे अनिवार्य रूप से कहते हैं "अरे, स्विच कुछ मामलों में बहुत अच्छा काम करता है, कुछ अन्य में नहीं।"


[संपादित करें] मैंने निम्नलिखित कारणों के लिए शीर्ष क्रम के उत्तर के साथ जाने का फैसला किया है (प्रत्येक ग्राहक के लिए एक अलग "ग्राहक" वर्ग बनाएं जो एक मानक इंटरफ़ेस लागू करता है):

  1. संगति: मैं एक इंटरफ़ेस बना सकता हूं जो सभी ग्राहक वर्गों को प्राप्त करता है और एक ही आउटपुट प्राप्त करता है, भले ही किसी अन्य डेवलपर द्वारा बनाया गया हो

  2. रख-रखाव: सभी कोड एक ही भाषा (जावा) में लिखे गए हैं, इसलिए किसी अन्य को अलग कोडिंग भाषा सीखने की आवश्यकता नहीं है ताकि यह सुनिश्चित हो सके कि एक मृत-सरल सुविधा क्या होनी चाहिए।

  3. पुन: उपयोग: कोड में एक समान समस्या फसलों के मामले में, मैं "कस्टम" तर्क को लागू करने के लिए किसी भी संख्या को रखने के लिए ग्राहक वर्ग का पुन: उपयोग कर सकता हूं।

  4. परिचित: मैं पहले से ही जानता हूं कि यह कैसे करना है, इसलिए मैं इसे जल्दी से प्राप्त कर सकता हूं और अन्य, अधिक दबाव वाले मुद्दों पर आगे बढ़ सकता हूं।

कमियां:

  1. प्रत्येक नए ग्राहक को नए ग्राहक वर्ग के संकलन की आवश्यकता होती है, जो परिवर्तनों को संकलित और तैनात करने के तरीके में कुछ जटिलता जोड़ सकता है।

  2. प्रत्येक नए ग्राहक को एक डेवलपर द्वारा जोड़ा जाना है - एक समर्थन व्यक्ति केवल गुण फ़ाइल जैसी किसी चीज़ में तर्क नहीं जोड़ सकता है। यह आदर्श नहीं है ... लेकिन फिर मुझे भी यकीन नहीं था कि एक समर्थन व्यक्ति आवश्यक व्यावसायिक तर्क को कैसे लिख पाएगा, खासकर अगर यह कई अपवादों के साथ जटिल है (जैसा कि संभावना है)।

  3. यदि हम कई, कई नए ग्राहकों को जोड़ते हैं तो यह अच्छा नहीं होगा। यह अपेक्षित नहीं है, लेकिन अगर ऐसा होता है तो हमें कोड के कई अन्य हिस्सों के साथ-साथ इस एक पर भी पुनर्विचार करना होगा।

आप में से रुचि रखने वालों के लिए, आप नाम से एक वर्ग को कॉल करने के लिए जावा प्रतिबिंब का उपयोग कर सकते हैं:

Payment payment = getPaymentFromSomewhere();

try {
    String nameOfCustomClass = propertiesFile.get("customClassName");
    Class<?> cpp = Class.forName(nameOfCustomClass);
    CustomPaymentProcess pp = (CustomPaymentProcess) cpp.newInstance();

    payment = pp.processPayment(payment);
} catch (Exception e) {
    //handle the various exceptions
} 

doSomethingElseWithThePayment(payment);

1
शायद आपको गणना के प्रकार के बारे में विस्तार से बताना चाहिए। क्या यह सिर्फ एक छूट की गणना है या यह एक अलग कार्य प्रवाह है?
qwerty_so

@ThomasKilian यह केवल एक उदाहरण है। भुगतान ऑब्जेक्ट की कल्पना करें, और गणना कुछ ऐसी हो सकती है जैसे "Payment.total द्वारा Payment.percentage को गुणा करें - लेकिन नहीं तो Payment.id 'R' से शुरू होता है"। उस तरह की ग्रैन्युलैरिटी। हर ग्राहक के अपने नियम होते हैं।
एंड्रयू


क्या आपने कुछ इस तरह की कोशिश की है । प्रत्येक ग्राहक के लिए अलग-अलग सूत्र निर्धारित करना।
Laiv

1
विभिन्न उत्तरों से सुझाए गए प्लग-इन केवल तभी काम करेंगे जब आपके पास एक समर्पित-प्रति-ग्राहक उत्पाद हो। यदि आपके पास एक सर्वर समाधान है जहां आप गतिशील रूप से ग्राहक आईडी की जांच करते हैं, तो यह काम नहीं करेगा। तो आपका पर्यावरण क्या है?
qwerty_so 10

जवाबों:


14

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

मेरे दिमाग में दो विकल्प आते हैं।

विकल्प 1: अपनी कक्षा को एक सार वर्ग बनाएँ, जहाँ वह विधि जो ग्राहकों के बीच बदलती है वह एक सार पद्धति है। फिर प्रत्येक ग्राहक के लिए एक उपवर्ग बनाएँ।

विकल्प 2: ग्राहक-निर्भर तर्क के सभी युक्त एक Customerवर्ग, या एक ICustomerइंटरफ़ेस बनाएँ । अपने भुगतान प्रसंस्करण वर्ग को ग्राहक आईडी स्वीकार करने के बजाय, यह एक वस्तु Customerया ICustomerवस्तु स्वीकार है । जब भी इसे कुछ ग्राहक-निर्भर करने की आवश्यकता होती है, तो यह उपयुक्त विधि कहता है।


ग्राहक वर्ग एक बुरा विचार नहीं है। प्रत्येक ग्राहक के लिए किसी प्रकार की कस्टम ऑब्जेक्ट होना आवश्यक है, लेकिन मैं स्पष्ट नहीं था कि यह DB रिकॉर्ड होना चाहिए, एक गुण फ़ाइल (किसी प्रकार की), या कोई अन्य वर्ग।
एंड्रयू

10

आप अपने एप्लिकेशन के लिए कस्टम गणना को "प्लग-इन" के रूप में लिखना चाह सकते हैं। उसके बाद, आप एक कॉन्फ़िगरेशन फ़ाइल का उपयोग करके आपको यह बताएंगे कि किस ग्राहक के लिए गणना प्लगइन का उपयोग किया जाना चाहिए। इस तरह, आपके मुख्य एप्लिकेशन को हर नए ग्राहक के लिए पुन: संकलित करने की आवश्यकता नहीं होगी - इसे केवल एक कॉन्फ़िगरेशन फ़ाइल पढ़ने (या फिर से पढ़ने) और नए प्लग-इन को लोड करने की आवश्यकता है।


धन्यवाद। जावा वातावरण को प्लग-इन कैसे कहा जा सकता है? उदाहरण के लिए, मैं सूत्र लिखना चाहता हूं "परिणाम = यदि (Payment.id.startsWith (" R "))? भुगतान। भुगतान * भुगतान। मूल: भुगतान। अन्य: ग्राहक के लिए एक संपत्ति के रूप में सहेजें, और इसे डालें उपयुक्त विधि में?
एंड्रयू

@ और, एक तरह से एक प्लगइन काम कर सकता है नाम से एक कक्षा में लोड करने के लिए प्रतिबिंब का उपयोग करें। कॉन्फ़िगरेशन फ़ाइल ग्राहकों के लिए कक्षाओं के नाम सूचीबद्ध करेगी। बेशक, आपके पास यह पहचानने का कोई तरीका होगा कि कौन सा प्लगइन किस ग्राहक के लिए है (उदाहरण के लिए, उसके नाम या कुछ मेटाडेटा कहीं संग्रहीत है)।
कैट

@ कैट धन्यवाद, यदि आप मेरे संपादित प्रश्न को पढ़ते हैं जो वास्तव में मैं इसे कैसे कर रहा हूं। दोष यह है कि एक डेवलपर को एक नया वर्ग बनाना पड़ता है जो स्केलेबिलिटी को सीमित करता है - मैं एक समर्थन व्यक्ति को सिर्फ एक गुण फ़ाइल संपादित करना पसंद कर सकता हूं, लेकिन मुझे लगता है कि बहुत अधिक जटिलता है।
एंड्रयू

@ संकेत: आप अपने फॉर्मूले को एक गुण फ़ाइल में लिखने में सक्षम हो सकते हैं, लेकिन तब आपको किसी प्रकार के अभिव्यक्ति पार्सर की आवश्यकता होगी। और आप एक दिन एक सूत्र में भाग सकते हैं जो बहुत जटिल है (आसानी से) गुण फ़ाइल में एक-पंक्ति अभिव्यक्ति के रूप में लिखें। यदि आप वास्तव में चाहते हैं कि गैर-प्रोग्रामर इन पर काम करने में सक्षम हों, तो आपको उनके उपयोग के लिए किसी प्रकार के उपयोगकर्ता के अनुकूल अभिव्यक्ति संपादक की आवश्यकता होगी जो आपके एप्लिकेशन के लिए कोड उत्पन्न करेगा। यह किया जा सकता है (मैंने इसे देखा है), लेकिन यह तुच्छ नहीं है।
FrustratedWithFormsDesigner

4

मैं गणनाओं का वर्णन करने के लिए एक नियम के साथ जाऊंगा। यह किसी भी दृढ़ता की दुकान में आयोजित किया जा सकता है और गतिशील रूप से संशोधित किया जा सकता है।

एक विकल्प के रूप में इस पर विचार करें:

customerOps = [oper1, oper2, ..., operN]; // array with customer specific operations
index = customerOpsIndex(customer);
customerOps[index](parms);

जहां customerOpsIndexसही ऑपरेशन इंडेक्स की गणना की जाती है (आप जानते हैं कि किस ग्राहक को किस उपचार की आवश्यकता है)।


अगर मैं एक व्यापक नियम बना सकता हूं तो मैं करूंगा। लेकिन प्रत्येक नए ग्राहक के पास नियमों का अपना सेट हो सकता है। इसके अलावा, मैं पूरी बात को कोड में शामिल करना पसंद करूंगा, अगर ऐसा करने के लिए एक डिज़ाइन पैटर्न है। मेरा स्विच {} उदाहरण यह काफी अच्छी तरह से करता है, लेकिन यह बहुत लचीला नहीं है।
एंड्रयू

आप किसी सरणी में ग्राहक के लिए बुलाए जाने वाले कार्यों को स्टोर कर सकते हैं और इसे इंडेक्स करने के लिए ग्राहक आईडी का उपयोग कर सकते हैं।
qwerty_so

यह अधिक आशाजनक लगता है। :)
एंड्रयू

3

नीचे जैसा कुछ:

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

public interface ICustomer
{
    int Calculate();
}
public class CustomerLogic101 : ICustomer
{
    public int Calculate() { return 101; }
}
public class CustomerLogic102 : ICustomer
{
    public int Calculate() { return 102; }
}

public class CustomerRepo
{
    public ICustomer GetCustomerById(
        string id)
    {
        var data;//get data from db
        if (data.logicType == "101")
        {
            return new CustomerLogic101();
        }
        if (data.logicType == "102")
        {
            return new CustomerLogic102();
        }
    }
}
public class Calculator
{
    public int CalculateCustomer(string custId)
    {
        CustomerRepo repo = new CustomerRepo();
        var cust = repo.GetCustomerById(custId);
        return cust.Calculate();
    }
}

2

ऐसा लगता है कि आपके पास कस्टम कोड से ग्राहकों के लिए 1 से 1 मैपिंग है और क्योंकि आप एक संकलित भाषा का उपयोग कर रहे हैं, इसलिए आपको हर बार एक नया ग्राहक प्राप्त करने के लिए अपने सिस्टम का पुनर्निर्माण करना होगा

एक एम्बेडेड स्क्रिप्टिंग भाषा का प्रयास करें।

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

package com.example;

import org.jruby.embed.LocalVariableBehavior;
import org.jruby.embed.ScriptingContainer;

public class Main {

    private ScriptingContainer ruby;

    public static void main(String[] args) {
        new Main().run();
    }

    public void run() {
        ruby = new ScriptingContainer(LocalVariableBehavior.PERSISTENT);
        // Assign the Java objects that you want to share
        ruby.put("main", this);
        // Execute a script (can be of any length, and taken from a file)
        Object result = ruby.runScriptlet("main.hello_world");
        // Use the result as if it were a Java object
        System.out.println(result);
    }

    public String getHelloWorld() {
        return "Hello, worlds!";
    }

}

यह एक बहुत ही सामान्य पैटर्न है। उदाहरण के लिए, कई कंप्यूटर गेम C ++ में लिखे गए हैं, लेकिन गेम में प्रत्येक प्रतिद्वंद्वी के ग्राहक व्यवहार को परिभाषित करने के लिए एम्बेडेड Lua स्क्रिप्ट का उपयोग करते हैं।

दूसरी ओर, यदि आपके पास कस्टम कोड से ग्राहकों के लिए कई 1 से मैपिंग है, तो पहले से ही सुझाए गए "रणनीति" पैटर्न का उपयोग करें।

यदि मैपिंग यूजर आईडी मेक पर आधारित नहीं है, तो matchप्रत्येक रणनीति ऑब्जेक्ट में एक फ़ंक्शन जोड़ें और ऑर्डर की गई पसंद का उपयोग करने के लिए ऑर्डर करें।

यहाँ कुछ छद्म कोड है

strategy = strategies.find { |strategy| strategy.match(customer) }
strategy.apply(customer, ...)

2
मैं इस दृष्टिकोण से बचूंगा। प्रवृत्ति उन सभी स्क्रिप्ट स्निपेट्स को डीबी में डालने की है और फिर आप स्रोत नियंत्रण, संस्करण और परीक्षण खो देते हैं।
इवान

काफी उचित। वे उन्हें अलग-अलग गिट रेपो या जहां कहीं भी रखते हैं, वहां सबसे अच्छे से स्टोर करते हैं। मेरे जवाब को अपडेट करने के लिए कहना है कि स्निपेट्स को आदर्श रूप से संस्करण नियंत्रण में होना चाहिए।
अकुंठ

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

2

मैं करंट के खिलाफ तैरने जा रहा हूं।

मैं ANTLR के साथ अपनी अभिव्यक्ति की भाषा को लागू करने की कोशिश करूंगा ।

अब तक, सभी उत्तर दृढ़ता से कोड अनुकूलन पर आधारित हैं। प्रत्येक ग्राहक के लिए ठोस कक्षाओं को लागू करना मुझे लगता है कि, भविष्य में कुछ बिंदु पर, अच्छी तरह से पैमाने पर नहीं जा रहा है। रखरखाव महंगा और दर्दनाक होने जा रहा है।

तो, Antlr के साथ, विचार अपनी भाषा को परिभाषित करना है। कि आप उपयोगकर्ताओं (या देवों) को ऐसी भाषा में व्यावसायिक नियम लिखने की अनुमति दे सकते हैं।

उदाहरण के रूप में अपनी टिप्पणी लेना:

मैं सूत्र लिखना चाहता हूं "परिणाम = यदि (Payment.id.startsWith (" R ")); भुगतान। भुगतान * Payment.total: Payment.otherValue"

अपने ईएल के साथ, आपके लिए राज्य वाक्यों की तरह संभव होना चाहिए:

If paymentID startWith 'R' then (paymentPercentage / paymentTotal) else paymentOther

फिर...

ग्राहक के लिए एक संपत्ति के रूप में सहेजें, और उचित विधि में डालें?

आप ऐसा कर सकते हैं। यह एक स्ट्रिंग है, आप इसे संपत्ति या विशेषता के रूप में सहेज सकते हैं।

मैं झूठ नहीं बोलूंगा। यह काफी जटिल और कठिन है। यदि व्यवसाय के नियम भी जटिल हैं तो यह और भी कठिन है।

यहाँ कुछ SO प्रश्न जो आपकी रुचि के हो सकते हैं:


नोट: ANTLR पायथन और जावास्क्रिप्ट के लिए भी कोड तैयार करता है। यह बहुत अधिक उपरि के बिना अवधारणा के प्रमाण लिखने में मदद कर सकता है।

यदि आपको एंट्रेल बहुत कठिन लगता है, तो आप Expr4J, JEval, Parsii जैसे कामों के साथ प्रयास कर सकते हैं। ये उच्च स्तर की अमूर्तता के साथ काम करते हैं।


यह एक अच्छा विचार है लेकिन रेखा के नीचे अगले आदमी के लिए एक रखरखाव सिरदर्द है। लेकिन जब तक मैंने मूल्यांकन नहीं किया है और सभी चरों को तौला है, तब तक मैं किसी भी विचार को त्यागने वाला नहीं हूं।
एंड्रयू

1
आपके पास कई विकल्प बेहतर हैं। मैं सिर्फ एक और देना चाहता था
Laiv

Theres इस बात से इनकार नहीं करते कि यह एक वैध दृष्टिकोण है, बस websphere या अन्य शेल्फ एंटरप्राइज सिस्टम को देखें जो 'अंतिम उपयोगकर्ता को अनुकूलित कर सकते हैं' लेकिन @akuhn की तरह नकारात्मक पक्ष यह है कि अब आप 2 भाषाओं में प्रोग्रामिंग कर रहे हैं और अपना संस्करण खो रहे हैं / स्रोत नियंत्रण / परिवर्तन नियंत्रण
ईवान

@ मुझे खेद है, मुझे डर है कि मुझे आपके तर्क समझ में नहीं आए। भाषा विवरणकर्ता और ऑटोजेनरेटेड कक्षाएं परियोजना का हिस्सा या नहीं हो सकती हैं। लेकिन किसी भी मामले में मैं यह नहीं देखता कि मैं वर्जनिंग / सोर्स कोड मैनेजमेंट क्यों खो सकता हूं। दूसरी ओर, ऐसा लग सकता है कि 2 अलग-अलग भाषाएं हैं, लेकिन यह अस्थायी है। भाषा हो जाने के बाद, आप केवल तार सेट करते हैं। जैसे क्रोन एक्सप्रेशन। लंबे समय से कम चिंता की बात है।
Laiv

"अगर भुगतान शुरू होता है तो 'आर' तब (पेमेंट परसेंटेज / पेमेंट टूटल) पेमेंट ओथर" इसे कहां स्टोर करें? क्या संस्करण है? यह किस भाषा में लिखी गई है? आपको इसके लिए कौन सी इकाई परीक्षण मिला है?
इवान

1

आप कम से कम एल्गोरिदम को बाहरी बना सकते हैं ताकि ग्राहक वर्ग को बदलने की आवश्यकता न हो जब एक नया ग्राहक रणनीति पैटर्न नामक एक डिज़ाइन पैटर्न का उपयोग करके जोड़ा जाता है (यह गैंग ऑफ़ फोर में है)।

आपके द्वारा दिए गए स्निपेट से, यह तर्कपूर्ण है कि क्या रणनीति पैटर्न कम बनाए रखने या अधिक बनाए रखने योग्य होगा, लेकिन यह कम से कम ग्राहक वर्ग के ज्ञान को खत्म कर देगा कि क्या किया जाना चाहिए (और आपके स्विच केस को खत्म कर देगा)।

एक StrategyFactory वस्तु एक CustomerIntf सूचक (या संदर्भ) CustomerID के आधार पर बनाएगा। फ़ैक्टरी उन ग्राहकों के लिए एक डिफ़ॉल्ट कार्यान्वयन लौटा सकती है जो विशेष नहीं हैं।

ग्राहक वर्ग को केवल फैक्टरी से सही रणनीति के लिए पूछना चाहिए और फिर उसे कॉल करना चाहिए।

यह बहुत संक्षिप्त छद्म सी ++ है जो आपको दिखाता है कि मेरा क्या मतलब है।

class Customer
{
public:

    void doCalculations()
    {
        CalculationsStrategyIntf& strategy = CalculationsStrategyFactory::instance().getStrategy(*this);
        strategy.doCalculations();
    }
};


class CalculationsStrategyIntf
{
public:
    virtual void doCalculations() = 0;
};

इस समाधान का दोष यह है कि, प्रत्येक नए ग्राहक के लिए, जिसे विशेष तर्क की आवश्यकता होती है, आपको गणनाओं का एक नया कार्यान्वयन बनाने की आवश्यकता होगी। यह उपयुक्त ग्राहक के लिए इसे वापस करने के लिए कारखाने को अपडेट करना होगा। इसके लिए भी संकलन की आवश्यकता है। लेकिन आप कम से कम ग्राहक वर्ग में बढ़ते स्पेगेटी कोड से बचेंगे।


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

-1

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.