এমন একটি পদ্ধতি কল করার সর্বোত্তম উপায় কোনটি যা কেবলমাত্র এক শ্রেণীর জন্য উপলব্ধ যা একটি ইন্টারফেস প্রয়োগ করে তবে অন্যটি নয়?


11

মূলত আমাকে একটি নির্দিষ্ট শর্তের ভিত্তিতে বিভিন্ন ক্রিয়া সম্পাদন করতে হবে। বিদ্যমান কোডটি এভাবে লেখা হয়

বেস ইন্টারফেস

// DoSomething.java
interface DoSomething {

   void letDoIt(String info);
}

প্রথম শ্রমিক শ্রেণি বাস্তবায়ন

class DoItThisWay implements DoSomething {
  ...
}

দ্বিতীয় শ্রমিক শ্রেণি বাস্তবায়ন

class DoItThatWay implements DoSomething {
   ...
}

মূল ক্লাস

   class Main {
     public doingIt(String info) {
        DoSomething worker;
        if (info == 'this') {
          worker = new DoItThisWay();
        } else {
          worker = new DoItThatWay();
        }
        worker.letDoIt(info)
     }

এই কোডটি ঠিকঠাক কাজ করে এবং বোঝা সহজ।

এখন, একটি নতুন প্রয়োজনীয়তার কারণে, আমার কাছে একটি নতুন তথ্য সরবরাহ করা দরকার যা কেবলমাত্র বোধগম্য DoItThisWay

আমার প্রশ্নটি: নিম্নলিখিত কোডিং শৈলীটি এই প্রয়োজনীয়তাটি পরিচালনা করতে ভাল করে?

নতুন শ্রেণীর পরিবর্তনশীল এবং পদ্ধতি ব্যবহার করুন

// Use new class variable and method

class DoItThisWay implements DoSomething {
  private int quality;
  DoSomething() {
    quality = 0;
  }

  public void setQuality(int quality) {
    this.quality = quality;
  };

 public void letDoIt(String info) {
   if (quality > 50) { // make use of the new information
     ...
   } else {
     ...
   }
 } ;

}

যদি আমি এটি এইভাবে করি তবে আমার কলারের সাথে সম্পর্কিত পরিবর্তন করা দরকার:

   class Main {
     public doingIt(String info) {
        DoSomething worker;
        if (info == 'this') {
          int quality = obtainQualityInfo();
          DoItThisWay tmp = new DoItThisWay();
          tmp.setQuality(quality)
          worker = tmp;

        } else {
          worker = new DoItThatWay();
        }
        worker.letDoIt(info)
     }

এটি কি একটি ভাল কোডিং শৈলী? বা আমি এটি কাস্ট করতে পারি

   class Main {
     public doingIt(String info) {
        DoSomething worker;
        if (info == 'this') {
          int quality = obtainQualityInfo();
          worker = new DoItThisWay();
          ((DoItThisWay) worker).setQuality(quality)
        } else {
          worker = new DoItThatWay();
        }
        worker.letDoIt(info)
     }

19
কেন কেবল qualityকনস্ট্রাক্টরের জন্য পাস করবেন না DoItThisWay?
ডেভিড আরনো

আমার সম্ভবত আমার প্রশ্নটি সংশোধন করা দরকার ... কারণ পারফরম্যান্সের কারণে নির্মাতারা নির্মাণের কাজটি তৈরি করেছেন DoItThisWayএবং DoItThatWayএকবার হয়ে গেছে MainMainএটি একটি দীর্ঘ জীবিত শ্রেণি এবং doingItএটি বহুবার এবং বারবার বলা হয়।
অ্যান্টনি কং

হ্যাঁ, আপনার প্রশ্ন আপডেট করা সেক্ষেত্রে ভাল ধারণা হবে।
ডেভিড আরনো

আপনি কি বলতে চাইছেন যে কোনও setQualityকিছুর পরে এই DoItThisWayবস্তুটির জীবদ্দশায় একাধিকবার ডাকা হবে ?
jpmc26

1
আপনার উপস্থাপিত দুটি সংস্করণের মধ্যে কোনও প্রাসঙ্গিক পার্থক্য নেই। যৌক্তিক দৃষ্টিকোণ থেকে তারা একই কাজ করে।
সেবাস্তিয়ান রেডল

উত্তর:


6

আমি ধরে নিচ্ছি যে এ- qualityতে প্রতিটি letDoIt()কলের পাশাপাশি সেট করা দরকার DoItThisWay()

ইস্যু আমি এখানে উদ্ভূত দেখুন এই হল: আপনি প্রবর্তন করছি সময়গত কাপলিং (অর্থাত কি happends আপনাকে কল করার ভুলে গিয়ে থাকেন setQuality()কল করার আগে letDoIt()একটি উপর DoItThisWay?)। আর এর জন্য বাস্তবায়নের DoItThisWayএবং DoItThatWayউত্পথ হয় (এক চাহিদা আছে setQuality(), বলা অন্যান্য নয়)।

যদিও এই মুহূর্তে সমস্যাগুলির কারণ নাও হতে পারে, তবে শেষ পর্যন্ত এটি আপনাকে হতাশ করতে পারে। এটি অন্য দিকে নেওয়া letDoIt()এবং বিবেচনা করা সার্থক হতে পারে যে মানের মানের তথ্যটি infoআপনাকে এর মধ্য দিয়ে যাওয়ার অংশ হতে পারে কিনা; তবে এটি বিশদ নির্ভর করে।


15

এটি কি একটি ভাল কোডিং শৈলী?

আমার দৃষ্টিকোণ থেকে আপনার সংস্করণ দুটি হয় না। কল setQualityকরার আগে প্রথমে ফোন letDoItকরা একটি অস্থায়ী সংযুক্তি । আপনি এর উদ্দীপনা DoItThisWayহিসাবে দেখা আটকে DoSomethingগেছেন, তবে এটি (কমপক্ষে কার্যকরীভাবে নয়), এটি বরং এর মতো কিছু

interface DoSomethingWithQuality {
   void letDoIt(String info, int quality);
}

এটি Mainবরং কিছু করতে হবে

class Main {
    // omitting the creation
    private DoSomething doSomething;
    private DoSomethingWithQuality doSomethingWithQuality;

    public doingIt(String info) {
        DoSomething worker;
        if (info == 'this') {
            int quality = obtainQualityInfo();
            doSomethingWithQuality.letDoIt(info, quality);
        } else {
            doSomething.letDoIt(info);
        }
    }
}

আপনি অন্যদিকে ক্লাসগুলিতে প্যারামিটারগুলি সরাসরি ক্লাসগুলিতে পাস করতে পারেন (এটি সম্ভব বলে ধরে নিচ্ছেন) এবং কোন কারখানায় কোনটি ব্যবহার করবেন সে সিদ্ধান্তটি অর্পণ করতে পারেন (এটি উদাহরণগুলি আবার বিনিময়যোগ্য করে দেবে এবং উভয়ই উদ্ভূত হতে পারে DoSomething)। এটি Mainএই মত চেহারা করতে হবে

class Main {
    private DoSomethingFactory doSomethingFactory;

     public doingIt(String info) {
         int quality = obtainQualityInfo();
         DoSomething doSomethingWorker = doSomethingFactory.Create(info, quality);
         doSomethingWorker.letDoIt();
     }
}

আমি সচেতন যে আপনি এটি লিখেছিলেন

কারণ কার্য সম্পাদনের কারণে ডোইটিটিস ওয়ে এবং ডওটিটওয়ে নির্মাণের কাজটি একবার মূল নির্মাতায় করা হয়

তবে আপনি কারখানায় তৈরি করা ব্যয়বহুল অংশগুলি ক্যাশে করতে এবং সেগুলি কনস্ট্রাক্টরের কাছেও দিতে পারেন।


আরগ, আমি উত্তর টাইপ করার সময় আপনি আমাকে গুপ্তচরবৃত্তি করছেন? আমরা এই জাতীয় অনুরূপ পয়েন্টগুলি তৈরি করি (তবে আপনার অনেক বেশি বিস্তৃত এবং সুস্পষ্ট);)
চারনএক্স

1
@ ডকব্রাউন হ্যাঁ, এটি বিতর্কযোগ্য, তবে যেহেতু DoItThisWayপ্রয়োজনীয়তার জন্য letDoItএটি আলাদাভাবে আচরণ করার আগে ফোনটি মান নির্ধারণ করা প্রয়োজন । আমি আশা করি যে DoSomethingসমস্ত ডেরাইভেটিভের জন্য একইভাবে কাজ করার আগে (মানটি নির্ধারণ না করা)। এটা কোনো কিছু হলো? অবশ্যই এটি ধোঁয়াটে ধরণের, যেহেতু আমরা যদি setQualityকারখানার পদ্ধতি থেকে কল করি তবে ক্লায়েন্টটি মান নির্ধারণ করতে হবে কিনা তা সম্পর্কে অজ্ঞেয়বাদী হবে।
পল কার্টেসার

2
@ ডকব্রাউন আমি চুক্তিটি letDoIt()হ'ল (কোনও অতিরিক্ত তথ্যের অভাবে) "যদি আপনি আমাকে সরবরাহ করেন তবে আমি সঠিকভাবে কার্যকর করতে পারি (যা কিছু করি তা করতে পারি) String info"। setQuality()আগে থেকে যে কল করা প্রয়োজন তা কল করার পূর্বশর্তকে শক্তিশালী করে letDoIt()এবং এভাবে এলএসপির লঙ্ঘন হবে।
চারনএক্স

2
@ চ্যারনএক্স: উদাহরণস্বরূপ, যদি এমন একটি চুক্তি রয়েছে যাতে বোঝানো হয় যে " letDoIt" কোনও ব্যতিক্রম ছুঁড়ে না ফেলে এবং "সেটকুয়ালিটি" বলতে ভুলে গেলেও তার letDoItব্যতিক্রম ছুঁড়ে ফেলা হয়, তবে আমি সম্মত হব, এ জাতীয় বাস্তবায়ন এলএসপি লঙ্ঘন করবে। তবে সেগুলি আমার কাছে খুব কৃত্রিম অনুমানের মতো দেখাচ্ছে।
ডক ব্রাউন

1
এটি একটি ভাল উত্তর। কেবলমাত্র আমি যুক্ত করব একটি কোড বেসের জন্য কতটা ভয়াবহভাবে মন্দ টেম্পোরাল কাপলিং তা নিয়ে কিছু মন্তব্য। এটি আপাতদৃষ্টিতে decoupled উপাদানগুলির মধ্যে একটি লুকানো চুক্তি। সাধারণ মিলনের সাথে, অন্তত এটি স্পষ্ট এবং সহজেই সনাক্তযোগ্য। এটি করা মূলত একটি গর্ত খনন করা এবং এটি পাতা দিয়ে আচ্ছাদন করা।
জিমি জেমস

10

ধরে নেওয়া যাক qualityকনস্ট্রাক্টরে পাস করা যাবে না, এবং কল করার setQualityপ্রয়োজন রয়েছে।

বর্তমানে একটি কোড স্নিপেট পছন্দ করে

    int quality = obtainQualityInfo();
    worker = new DoItThisWay();
    ((DoItThisWay) worker).setQuality(quality);

এটিতে খুব বেশি চিন্তাভাবনা করার উপায় এটি খুব ছোট। আইএমএইচও এটি দেখতে খানিকটা কুৎসিত দেখাচ্ছে, তবে বুঝতে খুব কষ্ট হয় না।

যখন এই জাতীয় কোড স্নিপেট বৃদ্ধি পায় এবং রিফ্যাক্টোরের কারণে আপনার মতো কিছু শেষ হয় তখন সমস্যা দেখা দেয়

    int quality = obtainQualityInfo();
    worker = CreateAWorkerForThisInfo();
    ((DoItThisWay) worker).setQuality(quality);

এখন, আপনি তত্ক্ষণাত্ সেই কোডটি সঠিক কিনা তা দেখতে পাবেন না, এবং সংকলক আপনাকে বলবে না। সুতরাং সঠিক ধরণের একটি অস্থায়ী পরিবর্তনশীল প্রবর্তন করা, এবং অভিনেতাকে এড়িয়ে চলা কোনও বাস্তব অতিরিক্ত প্রচেষ্টা ছাড়াই কিছুটা বেশি টাইপ-নিরাপদ।

তবে, আমি আসলে tmpআরও ভাল নাম দেব :

      int quality = obtainQualityInfo();
      DoItThisWay workerThisWay = new DoItThisWay();
      workerThisWay.setQuality(quality)
      worker = workerThisWay;

এই জাতীয় নামকরণ ভুল কোডকে ভুল দেখতে সহায়তা করে


tmp এর চেয়ে আরও ভাল নামকরণ করা যেতে পারে "কর্মীঘাটিউসকুয়ালিটি"
ব্যবহারকারী 949300

1
@ ব্যবহারকারী949300: আইএমএইচও এটি ভাল ধারণা নয়: ধরে নিন DoItThisWayআরও সুনির্দিষ্ট প্যারামিটারগুলি পাওয়া যায় - আপনার পরামর্শ অনুসারে প্রতিবার নাম পরিবর্তন করা দরকার। নাম ভোর ভেরিয়েবল ব্যবহার করা আরও ভাল যা কোন বস্তুর নাম উপলভ্য নয়, যা বস্তুর প্রকারটি পরিষ্কার করে দেয়।
ডক ব্রাউন

স্পষ্ট করার জন্য, এটি শ্রেণীর নাম নয়, চলকের নাম হবে। আমি সম্মত হই যে ক্লাসের নামে সমস্ত ক্ষমতা রাখাই একটি দুর্বল ধারণা। সুতরাং আমি workerThisWayএমন কিছু হওয়ার পরামর্শ দিচ্ছি usingQuality। সেই ছোট কোড স্নিপেটে এটি আরও সুনির্দিষ্ট হওয়া নিরাপদ। (এবং যদি তাদের ডোমেনের মধ্যে "ব্যবহারকার্যতা" ব্যবহার করার চেয়ে আরও ভাল বাক্যাংশ থাকে তবে
ব্যবহারকারী949300

2

একটি সাধারণ ইন্টারফেস যেখানে রানটাইম ডেটার উপর ভিত্তি করে সূচনা পরিবর্তিত হয় সাধারণত ফ্যাক্টরি প্যাটার্নে নিজেকে ধার দেয়।

DoThingsFactory factory = new DoThingsFactory(thingThatProvidesQuality);
DoSomething doSomething = factory.getDoer(info);

doSomething.letDoIt();

তারপরে ডোথিংসফ্যাক্টরি getDoer(info)ডসোমিং ইন্টারফেসে কংক্রিট DoThingsWithQual বস্তু নিক্ষেপ করার পূর্বে পদ্ধতির অভ্যন্তরে মানের তথ্য পাওয়ার এবং সেট করার বিষয়ে চিন্তা করতে পারে ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.