ओओपी डिजाइन मौजूदा डिजाइन में कोई संशोधन पर विचार नहीं कर रहा है

Aug 17 2020

प्रश्न है:

interface Animal {
    void eat();
}

class Lion implements Animal{    
    public void eat(){
        //do somethng
    }
}


class Test {
    public static void main(String[] args) {
        Animal lion = new Lion();
        lion.eat();
        lion.eat();
        lion.eat();
    }
}

आवश्यकता इस बात की गणना करने के लिए है कि इंटरफ़ेस और वर्ग को संशोधित किए बिना खाने की विधि को कितनी बार कहा जाता है।

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

क्या ऐसा करने का कोई अनुकूलित तरीका है।

प्रकाशन प्रकाशित करें एक तरीका है, लेकिन हमारे पास इंटरफ़ेस या लॉयन क्लास को संशोधित करने की अनुमति नहीं है।

जवाब

25 TulainsCórdova Aug 17 2020 at 15:07

आप उपशमन के बिना एक पशु के लिए अतिरिक्त जिम्मेदारियों को जोड़ने के लिए डेकोरेटर पैटर्न का उपयोग कर सकते हैं।


public interface Animal {
    void eat();
}

public class Lion implements Animal {
    public void eat() {
        // do something
    }
}

/* In the original Decorator pattern, 
the decorator is an abstract class, 
but for the sake of brevity, 
in this example it's a concrete class. */

public class AnimalWithEatCountDecorator implements Animal {
        private Animal animalWeWantToCountEats;
        private int eatCount=0;

        public AnimalWithEatCountDecorator(Animal animal) {
            this.animalWeWantToCountEats= animal;
        }
        
        public void eat(){ 
            this.animalWeWantToCountEats.eat();
            this.eatCount++;
        }
        
        public int getEatCount() {
            return this.eatCount;
        }   
        
}  

public class Test {

    public static void main(String[] args) {
        AnimalWithEatCountDecorator lion = new AnimalWithEatCountDecorator(new Lion());
        lion.eat();
        lion.eat();
        lion.eat();
        
        System.out.println(lion.getEatCount());
    }

}

अपडेट करें

यदि हम डेकोरेटर पैटर्न के प्रति अधिक वफादार होना चाहते हैं तो हम गेट्टर का उपयोग बिल्कुल भी नहीं कर सकते हैं getEatCount()और इसके बजाय कंस्ट्रक्टर में एक काउंटर ऑब्जेक्ट इंजेक्ट करें।

public interface Counter {
    public void increment();
    public int getCount();
}

/* I will omit the trivial implementation of Counter */ 

public class AnimalWithEatCountDecorator implements Animal {
        private Animal animalWeWantToCountEats;
        private Counter counterThingy;
        
        public AnimalWithEatCountDecorator(Animal animal, Counter counterThingy) {
            this.animalWeWantToCountEats= animal;
            this.counterThingy=counterThingy;
        }
        
        public void eat(){ 
            this.animalWeWantToCountEats.eat();
            this.counterThingy.increment();;
        }
        
}

public class Test {

    public static void main(String[] args) {
        Counter counterThingy = new CounterThingy();
        AnimalWithEatCountDecorator lion = 
                new AnimalWithEatCountDecorator(new Lion(), counterThingy);
        lion.eat();
        lion.eat();
        lion.eat();
        
        System.out.println(counterThingy.getCount());


    }

}

22 RobertBräutigam Aug 17 2020 at 14:39

रचना के लिए सही समय। Animalगिनती का एक नया कार्यान्वयन बनाएँ , लेकिन "वास्तविक" फ़ंक्शन को भी दर्शाता है। ऐशे ही:

public final class LoggingAnimal implements Animal {
   private final Animal delegate;
   private int eatCount = 0;

   public LoggingAnimal(Animal delegate) {
      this.delegate = delegate;
   }

   @Override
   public void eat() {
      eatCount++;
      delegate.eat();
      log("Animal ate {} times", eatCount); // Pseudo-functionality
   }
}

आपको किसी भी मौजूदा वर्ग को संशोधित करने की आवश्यकता नहीं है, और आप इसे अपने Animalइच्छित किसी भी कार्यान्वयन के साथ जोड़ सकते हैं। इस तरह इस्तेमाल करें:

Animal lion = new LoggingAnimal(new Lion());
lion.eat();
1 candied_orange Aug 17 2020 at 14:01

नए व्यवहार के साथ एक नई कक्षा बनाएँ। फिर कक्षा mainमें अद्यतन करें Test

class Test {
    public static void main(String[] args) {
        Animal lion = new AnimalThatKeepsAMealLog();
        lion.eat();
        lion.eat();
        lion.eat();
    }
}

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

Shadov Aug 18 2020 at 23:35

एक अलग दृष्टिकोण की तरह, जो आपको केवल कुछ ही बार किए गए कार्यों के लिए 50 कक्षाएं लेने से बचने की अनुमति देगा। यह एक अधिक सामान्य है, तकनीकी पहलुओं में बहुत उपयोगी है, जितना व्यवसाय में नहीं है, फिर भी यह बहुत उपयोगी हो सकता है।

btw बिल्डर सिर्फ उदाहरण के लिए है, निश्चित रूप से आप इसे उस तरह का उपयोग करने की जरूरत नहीं है, यहाँ preEat / postEat महत्वपूर्ण हैं

class PointcutAnimal implements Animal {
    private Runnable preEat;
    private Runnable postEat;
    @NonNull
    private Animal downstream;
    
    @Override
    public void eat() {
        if(preEat != null)
            preEat.run();
        
        downstream.eat();
        
        if(postEat != null)
            postEat.run();
    }
}

class Test {
    public static void main(String[] args) {
        AtomicInteger eatCount = new AtomicInteger(0);
    
        Animal lion = PointcutAnimal.builder(new Lion())
            .postEat(eatCount::getAndIncrement)
            .build();
            
        lion.eat();
        lion.eat();
        lion.eat();
        
        System.out.println(eatCount.get());
    }
}