বৃহত অবজেক্ট শ্রেণিবিন্যাসের সাথে দর্শনার্থীর প্যাটার্ন ব্যবহার করা


12

প্রসঙ্গ

আমি অবজেক্টের শ্রেণিবিন্যাসের সাথে ব্যবহার করছি (একটি অভিব্যক্তি গাছ) একটি "সিউডো" ভিজিটর প্যাটার্ন (ছদ্ম, যেমন এটি ডাবল প্রেরণ ব্যবহার করে না):

 public interface MyInterface
 {
      void Accept(SomeClass operationClass);
 }

 public class MyImpl : MyInterface 
 {
      public void Accept(SomeClass operationClass)
      {   
           operationClass.DoSomething();
           operationClass.DoSomethingElse();
           // ... and so on ...
      }
 }

এই নকশাটি অবশ্য প্রশ্নবিদ্ধ, মাইন্টারফেস বাস্তবায়নের সংখ্যাটি উল্লেখযোগ্য (50 ডলার বা তার বেশি) হওয়ায় আমার পক্ষে অতিরিক্ত ক্রিয়াকলাপগুলি যুক্ত করার প্রয়োজন হয়নি।

প্রতিটি বাস্তবায়ন স্বতন্ত্র (এটি একটি ভিন্ন অভিব্যক্তি বা অপারেটর), এবং কিছু সংমিশ্রণ (যেমন অপারেটর নোডগুলিতে অন্যান্য অপারেটর / লিফ নোড থাকবে)।

ট্র্যাভারসাল বর্তমানে গাছের মূল নোডে স্বীকৃতি অপারেশন কল করে সঞ্চালিত হয়, যার ফলে তার প্রতিটি শিশু নোডের কাছে স্বীকৃতি দেয়, যার ফলে ... এবং আরও ...

তবে এমন সময় এসেছে যখন আমার নতুন অপারেশন যুক্ত করা দরকার , যেমন সুন্দর মুদ্রণ:

 public class MyImpl : MyInterface 
 {
      // Property does not come from MyInterface
      public string SomeProperty { get; set; }

      public void Accept(SomeClass operationClass)
      {   
           operationClass.DoSomething();
           operationClass.DoSomethingElse();
           // ... and so on ...
      }

      public void Accept(SomePrettyPrinter printer)
      {
           printer.PrettyPrint(this.SomeProperty);
      }
 }    

আমি মূলত দুটি বিকল্প দেখতে পাচ্ছি:

  • রক্ষণাবেক্ষণের ব্যয়ে (প্রতিটি বিকল্প নয়, আইএমএইচও) প্রতিটি ব্যয়িত শ্রেণিতে আমার ক্রিয়াকলাপের জন্য একটি নতুন পদ্ধতি যুক্ত করে একই নকশাটি রাখুন
  • এক্সটেনসিবিলিটি ব্যয়ে "সত্য" দর্শনার্থী প্যাটার্নটি ব্যবহার করুন (কোনও বিকল্প নয়, যেমন আমি আরও বাস্তবায়নের পথে আসার প্রত্যাশা করি ...) সাথে দেখা দর্শন পদ্ধতির প্রায় 50+ ওভারলোড, প্রতিটি একটি নির্দিষ্ট প্রয়োগের সাথে মিলে যায় ?

প্রশ্ন

আপনি কি ভিজিটর প্যাটার্নটি ব্যবহার করে পুনঃনির্দেশ চান? অন্য কোনও প্যাটার্ন রয়েছে যা এই সমস্যাটি সমাধান করতে সহায়তা করতে পারে?


1
সম্ভবত সজ্জাকার একটি শৃঙ্খল আরও উপযুক্ত হবে?
ম্যাটডেভি

কিছু প্রশ্ন: এই বাস্তবায়নগুলি কীভাবে আলাদা? শ্রেণিবিন্যাসের কাঠামো কী? এবং সবসময় কি একই কাঠামো হয়? আপনার কি সর্বদা একই ক্রমে কাঠামোটি অতিক্রম করতে হবে?
জে কে।

@ ম্যাটড্যাভি: সুতরাং আপনি কি বাস্তবায়ন এবং অপারেশন অনুযায়ী একজন ডেকরেটার রেখেছেন?
টি ফ্যাব্রে

2
@ টি.ফ্যাব্রে এটি জানা মুশকিল। সেখানে 50+ এর বাস্তবায়নকারী রয়েছে MyInterface.. এই সমস্ত শ্রেণীর কি একটি অনন্য বাস্তবায়ন আছে DoSomethingএবং DoSomethingElse? আমি দেখতে পাই না যেখানে আপনার দর্শনার্থী শ্রেণি আসলে শ্রেণিবিন্যাসকে অতিক্রম করে - facadeএই মুহূর্তে এটি আরও অনেকটা দেখতে লাগে ..
ম্যাটড্যাভি

সি # এর কোন সংস্করণ এটি। তোমার কি ল্যাম্বদা আছে? বা লিনক? আপনার নিষ্পত্তি
জে কে।

উত্তর:


13

আমি তিনটি প্রোগ্রামিং ভাষায় ছয়টি বৃহত্তর প্রকল্পে 10+ বছর ধরে অভিব্যক্তি গাছগুলি উপস্থাপন করতে দর্শকের প্যাটার্নটি ব্যবহার করছি এবং ফলাফলটি নিয়ে আমি খুব সন্তুষ্ট। আমি বেশ কয়েকটি জিনিস পেয়েছি যা প্যাটার্নটি প্রয়োগ করা অনেক সহজ করে তুলেছে:

দর্শকের ইন্টারফেসে ওভারলোডগুলি ব্যবহার করবেন না

পদ্ধতির নামটিতে টাইপটি রাখুন, যেমন ব্যবহার করুন

IExpressionVisitor {
    void VisitPrimitive(IPrimitiveExpression expr);
    void VisitComposite(ICompositeExpression expr);
}

বরং

IExpressionVisitor {
    void Visit(IPrimitiveExpression expr);
    void Visit(ICompositeExpression expr);
}

আপনার ভিজিটর ইন্টারফেসে একটি "ধরা অজানা" পদ্ধতি যুক্ত করুন।

এটি এমন ব্যবহারকারীদের পক্ষে সম্ভব করে যারা আপনার কোডটি পরিবর্তন করতে পারে না:

IExpressionVisitor {
    void VisitPrimitive(IPrimitiveExpression expr);
    void VisitComposite(ICompositeExpression expr);
    void VisitExpression(IExpression expr);
};

এটি তাদের তাদের নিজস্ব বাস্তবায়ন তৈরি করতে দেয় IExpressionএবং IVisitorতাদের ক্যাচ-অল VisitExpressionপদ্ধতির প্রয়োগে রান-টাইম ধরণের তথ্য ব্যবহার করে তাদের এক্সপ্রেশনগুলিকে "বোঝে" ।

IVisitorইন্টারফেসের একটি ডিফল্ট করণীয় কিছুই প্রয়োগ করুন

এটি এমন ব্যবহারকারীদেরকে যা অভিব্যক্তি প্রকারের একটি উপসেটটি মোকাবেলা করতে হবে তাদের দর্শকদের দ্রুত তৈরি করতে এবং আপনার কোডটিতে আরও পদ্ধতি যুক্ত করে তাদের প্রতিরোধ ক্ষমতা তৈরি করতে দেয় IVisitor। উদাহরণস্বরূপ, আপনার এক্সপ্রেশন থেকে সমস্ত ভেরিয়েবলের নাম কাটা এমন কোনও ভিজিটরকে লেখা সহজ কাজ হয়ে যায় এবং আপনি IVisitorপরবর্তী সময়ে নতুন এক্সপ্রেশনের ধরণের একগুচ্ছ যোগ করলেও কোডটি ভেঙে যায় না ।


2
আপনি কেন স্পষ্ট করে বলতে পারেন Do not use overloads in the interface of the visitor?
স্টিভেন ইভার্স

1
আপনি ওভারলোড ব্যবহার করে কেন পুনরায় সুপারিশ করবেন না তা আপনি ব্যাখ্যা করতে পারেন? আমি কোথাও (ওডসাইন ডট কম এ পড়েছি) পড়েছি যে আমি ওভারলোডগুলি ব্যবহার করি বা না করি তা আসলেই গুরুত্বপূর্ণ নয়। আপনি যে নকশা পছন্দ করেন তার কোনও নির্দিষ্ট কারণ আছে?
টি ফ্যাব্রে

2
@ টি.ফ্যাব্রে এটি গতির দিক দিয়ে কিছু যায় আসে না, তবে এটি পঠনযোগ্যতার দিক থেকে গুরুত্বপূর্ণ। আমি যে তিনটি ভাষায় এটি প্রয়োগ করেছি এর দুটিতে পদ্ধতি সমাধানের জন্য ( জাভা এবং সি #) সম্ভাব্য ওভারলোডগুলির মধ্যে বেছে নেওয়ার জন্য একটি রান-টাইম পদক্ষেপ প্রয়োজন, এর ফলে বিশাল সংখ্যক ওভারলোডের কোডটি পড়া আরও কঠিন er কোডটি রিফ্যাকচার করাও সহজ হয়ে যায়, কারণ আপনি যে পদ্ধতিটি সংশোধন করতে চান তা চয়ন করা একটি তুচ্ছ কাজ হয়ে যায়।
dasblinkenlight

@ স্নোআরফাস দয়া করে উপরের টি.ফ্যাব্রায় আমার উত্তর দেখুন।
dasblinkenlight

@ ডাসব্লিংকনলাইট সি # এখন রান-টাইমটি কী ওভারলোডেড পদ্ধতিটি ব্যবহার করা উচিত (সংকলনের সময় নয়) তা নির্ধারণ করতে গতিশীল অফার দেয়। ওভারলোডিং ব্যবহার না করার কোনও কারণ আছে কি?
টিনটেনফাইচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.