দুটি শ্রেণীর মধ্যে বহু থেকে বহু সম্পর্কের প্রতিনিধিত্ব করার একটি ভাল উপায় কী?


10

ধরা যাক আমার কাছে দুটি এবং দুটি ধরণের অবজেক্ট রয়েছে, তাদের মধ্যে সম্পর্ক অনেকগুলি থেকে অনেকের মধ্যে, তবে তাদের দু'জনেরই অন্যটির মালিক নয়।

A এবং B উভয় দৃষ্টান্ত সংযোগ সম্পর্কে সচেতন হওয়া প্রয়োজন; এটি কেবল একটি উপায় নয়

সুতরাং, আমরা এটি করতে পারি:

class A
{
    ...

    private: std::vector<B *> Bs;
}

class B
{
    private: std::vector<A *> As;
}

আমার প্রশ্ন হ'ল সংযোগগুলি তৈরি করতে এবং ধ্বংস করতে আমি কোথায় ফাংশন রাখি?

এটি A :: সংযুক্তি (বি) হওয়া উচিত, যা পরে এ :: বিএস এবং বি :: ভেক্টর হিসাবে আপডেট করে?

বা এটি বি :: সংযুক্তি (এ) হওয়া উচিত, যা সমান যুক্তিযুক্ত বলে মনে হয়।

তাদের কেউই ঠিক মনে করেন না। যদি আমি কোডটি দিয়ে কাজ করা বন্ধ করি এবং এক সপ্তাহ পরে ফিরে আসি তবে আমি নিশ্চিত যে আমি এ.এটাচ (বি) বা বিআটাচ (এ) করছিলাম কিনা তা আমি মনে করতে পারব না।

সম্ভবত এটি এর মতো একটি ফাংশন হওয়া উচিত:

CreateConnection(A, B);

তবে একটি বৈশ্বিক ফাংশন তৈরি করাও অনাকাঙ্ক্ষিত বলে মনে হয়, এটি কেবল একটি এবং বি শ্রেণীর সাথে কাজ করার জন্য বিশেষত একটি ফাংশন given

আরেকটি প্রশ্ন: আমি যদি এই সমস্যা / প্রয়োজনীয়তাটি প্রায়শই চালাই তবে আমি কি কোনওভাবে এর জন্য একটি সাধারণ সমাধান করতে পারি? সম্ভবত একটি টুওয়ে কানেকশন ক্লাস যা থেকে এই ধরণের সম্পর্ক ভাগ করে নেওয়া ক্লাসগুলির মধ্যে থেকে আমি ব্যবহার করতে পারি বা ব্যবহার করতে পারি?

এই পরিস্থিতিটি পরিচালনা করার জন্য কিছু ভাল উপায় কী ... আমি জানি যে কীভাবে একের সাথে অনেকগুলি "সি এর মালিকানাধীন D" পরিস্থিতিটি বেশ ভালভাবে পরিচালনা করতে হয় তবে এটি একটি কৌশলপূর্ণ।

সম্পাদনা: কেবল এটি আরও সুস্পষ্ট করার জন্য, এই প্রশ্নটির মালিকানা সংক্রান্ত সমস্যা জড়িত না। এ এবং বি উভয়ই কিছু অন্য জেডের মালিকানাধীন, এবং জেড সমস্ত মালিকানা সংক্রান্ত বিষয়গুলির যত্ন নেয়। আমি কেবল এ এবং বি এর মধ্যে বহু-বহু সংযোগগুলি কীভাবে তৈরি করতে / সরাতে আগ্রহী তা সম্পর্কে


আমি একটি জেড :: সংযুক্তি তৈরি করব (এ, বি), সুতরাং, জেড যদি দুটি ধরণের অবজেক্টের মালিক হয় তবে তার পক্ষে সংযোগ তৈরির জন্য "সঠিক মনে হয়"। আমার (খুব ভাল নয়) উদাহরণে জেড A এবং B উভয়ের মধ্যেই একটি সংগ্রহস্থল হবে I প্রকৃত উদাহরণ ছাড়া আমি আর কোনও উপায় দেখতে পাচ্ছি না।
মাচাডো

1
আরও সুনির্দিষ্টভাবে বলতে গেলে, এ এবং বি এর বিভিন্ন মালিক থাকতে পারে। সম্ভবত এ জেডের মালিকানাধীন, বি এর মালিকানাধীন এক্স, যা ঘুরে ফিরে জেডের মালিকানাধীন you আপনি দেখতে পাচ্ছেন, এটি অন্য কোথাও লিঙ্কটি পরিচালনা করার চেষ্টা করে সত্যই সংশ্লেষিত হয়ে ওঠে। এ এবং বি এর সাথে যুক্ত হওয়া জোড়গুলির একটি তালিকা দ্রুত অ্যাক্সেস করতে সক্ষম হওয়া দরকার।
দিমিত্রি শুরালিভ

আপনি যদি আমার পরিস্থিতিতে ক এবং খের আসল নামগুলি সম্পর্কে আগ্রহী হন তবে তারা Pointerএবং GestureRecognizer। পয়েন্টারগুলি ইনপুট ম্যানেজার শ্রেণীর মালিকানাধীন এবং পরিচালিত হয়। অঙ্গভঙ্গি সনাক্তকারীদের উইজেট দৃষ্টান্তগুলির মালিকানা, যা কোনও স্ক্রিন উদাহরণ দ্বারা মালিকানাধীন হয় যা কোনও অ্যাপ্লিকেশন উদাহরণ দ্বারা মালিকানাধীন। পয়েন্টারগুলি গেসচাররনাকাইনাইজারদের জন্য নিযুক্ত করা হয় যাতে তারা তাদের কাঁচা ইনপুট ডেটা ফিড করতে পারে তবে জেচার রেকনাইজারদের তাদের সাথে বর্তমানে কতগুলি পয়েন্টার যুক্ত রয়েছে সে সম্পর্কে সচেতন হওয়া দরকার (1 আঙুল বনাম 2 আঙুলের অঙ্গভঙ্গি ইত্যাদি আলাদা করতে)।
দিমিত্রি শুরালিভ

এখন যখন আমি এটি সম্পর্কে আরও চিন্তা করি, মনে হচ্ছে আমি কেবল ফ্রেম-ভিত্তিক (পয়েন্টার ভিত্তিক না হয়ে) অঙ্গভঙ্গি স্বীকৃতি দেওয়ার চেষ্টা করছি। সুতরাং আমি পাশাপাশি পয়েন্টার-এ-এ-এ-সময় না হয়ে কেবল ফ্রেম-এ-সময়ে-সময়ে অঙ্গভঙ্গিতে ইভেন্টগুলি পাস করতে পারি। হুম।
দিমিত্রি শুরালিভ

উত্তর:


2

একটি উপায় হ'ল একটি সার্বজনীন Attach()পদ্ধতি এবং AttachWithoutReciprocating()প্রতিটি শ্রেণিতে একটি সুরক্ষিত পদ্ধতি যুক্ত করা। করুন Aএবং Bপারস্পরিক বন্ধুরা যাতে তাদের Attach()পদ্ধতি অপরের কল করতে পারেন AttachWithoutReciprocating():

A::Attach(B &b) {
    Bs.push_back(&b);
    b.AttachWithoutReciprocating(*this);
}

A::AttachWithoutReciprocating(B &b) {
    Bs.push_back(&b);
}

আপনি যদি এর জন্য অনুরূপ পদ্ধতিগুলি প্রয়োগ করেন তবে আপনাকে Bকোন শ্রেণিতে কল করতে হবে তা মনে করতে হবে না Attach()

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


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

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

সবকিছু সুচারুভাবে কাজ করে। যাইহোক, মূল প্রশ্নে আমার শেষ মন্তব্য অনুসারে, আমি বুঝতে শুরু করেছি যে আমি মূলত যা কল্পনা করেছি তার জন্য এই কার্যকারিতাটির দরকার নেই। এই 2-উপায় সংযোগগুলি ট্র্যাক করার পরিবর্তে, আমি প্রতিটি জোড়টিকে প্যারামিটার হিসাবে প্রয়োজনীয় ফাংশনে পৌঁছে দেব। তবে এটি পরবর্তী সময়ে কার্যকর হতে পারে।
দিমিত্রি শুরালিভ

MutuallyAttachableএই কাজের জন্য আমি যে ক্লাসটি লিখেছি তা এখানে রয়েছে , যদি কেউ এটি পুনরায় ব্যবহার করতে চান: goo.gl/VY9RB ( পাস্তবিন ) সম্পাদনা করুন: এই কোডটিকে একটি টেম্পলেট শ্রেণি তৈরি করে উন্নত করা যেতে পারে।
দিমিত্রি শুরাল্যাভ

1
আমি MutuallyAttachable<T, U>ক্লাসের টেম্পলেটটি জিস্টে রেখেছি । gist.github.com/3308058
দিমিত্রি শুরাল্যাভ

5

এটা কি সম্ভব জন্য সম্পর্ক নিজেই অতিরিক্ত বৈশিষ্ট্য আছে কিভাবে?

যদি তা হয় তবে তা আলাদা শ্রেণি হওয়া উচিত।

যদি তা না হয় তবে কোনও পারস্পরিক ক্রিয়াকলাপ তালিকা-পরিচালনা ব্যবস্থা যথেষ্ট will


যদি এটি একটি পৃথক শ্রেণি হয়, তবে এ কীভাবে তার বি এর সংযুক্ত দৃষ্টান্তগুলি জানতে পারে, এবং খ এর ক এর সংযুক্ত উদাহরণগুলি জানতে পারে? এই মুহুর্তে, এ এবং বি উভয়েরই সি-র সাথে 1-থেকে-বহু সম্পর্ক থাকা দরকার, তাই না?
দিমিত্রি শুরাল্যাভ

1
এ এবং বি উভয়েরই সি দৃষ্টান্ত সংগ্রহের জন্য একটি রেফারেন্স প্রয়োজন; সি রিলেশনাল মডেলিংয়ে 'ব্রিজ টেবিল' হিসাবে একই উদ্দেশ্যটি পরিবেশন করে
স্টিভেন এ লো লো

1

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

সংঘে স্থানান্তরিত করার জন্য একজন প্রার্থী হ'ল কোডটি যা প্রথম স্থানে সমিতি তৈরি করে। সম্ভবত attach()এটি কল করার পরিবর্তে কেবল একটি তালিকা সঞ্চয় করে std::pair<A, B>। যদি একাধিক জায়গা সমিতি তৈরি করে থাকে তবে এটি এক শ্রেণিতে বিমূর্ত করা যেতে পারে।

পদক্ষেপের জন্য অন্য প্রার্থী হ'ল সেই বিষয়টি যা Zআপনার ক্ষেত্রে সম্পর্কিত বস্তুগুলির মালিক ।

সংঘে স্থানান্তরিত করার জন্য আর একটি সাধারণ প্রার্থী হ'ল কোড যা ঘন ঘন পদ্ধতিতে বা বস্তুগুলিতে কল করে । উদাহরণস্বরূপ, কল করার পরিবর্তে , যা অভ্যন্তরীণভাবে সম্পর্কিত সমস্ত বস্তুর সাথে কিছু করে, এটি ইতিমধ্যে সমিতিগুলি জানে এবং প্রতিটিটির জন্য কল করে। আবার, যদি একাধিক জায়গাগুলি এটিকে কল করে তবে এটি একটি একক শ্রেণিতে বিমূর্ত করা যেতে পারে।ABa->foo()Ba->foo(b)

সংস্থাটি তৈরি, মালিকানা এবং ব্যবহারের অনেকগুলি বিষয় একই জিনিস হিসাবে ঘটে। এটি রিফ্যাক্টরিংটিকে খুব সহজ করে তুলতে পারে।

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

এই ধরণের রিফ্যাক্টরিং কোনও ম্যাজিক সূত্র নয় যা প্রতিবার কাজ করে। আপনি প্রতিটি পৃথক পরিস্থিতিতে উপযুক্ত ফিট না হওয়া পর্যন্ত আপনাকে এখনও পরীক্ষা করতে হবে, তবে আমি এটি প্রায় 95% সময়কালে কাজ করতে পেয়েছি। বাকি সময়গুলি আপনাকে কেবল বিশ্রীতার সাথে বাঁচতে হবে।


0

আমি যদি এটি প্রয়োগ করে থাকি তবে আমি সংযুক্তি পদ্ধতির অভ্যন্তরে এ এবং বি উভয় ক্ষেত্রেই সংযুক্তি রাখি, আমি তখন পাস করা বস্তুর সাথে সংযুক্তি বলব way এইভাবে আপনি এ.আটাচ (বি) বা বিআটাচ (কল) কল করতে পারেন ( ক)। আমার বাক্য গঠন সঠিক নাও হতে পারে, আমি বছরের পর বছর c ++ ব্যবহার করি নি:

class A {
  private: std::vector<B *> Bs;

  void Attach (B* obj) {
    // Only add obj if it's not in the vector
    if (std::find(Bs.begin(), Bs.end(), obj) == Bs.end()) {
      //Add obj to the vector
      Bs.push_back(obj);

      // Attach this class to obj
      obj->Attach(this);
    }
  }    
}

class B {
  private: std::vector<A *> As;

  void Attach (A* obj) {
    // Only add obj if it's not in the vector
    if (std::find(As.begin(), As.end(), obj) == As.end()) {
      //Add obj to the vector
      As.push_back(obj);

      // Attach this class to obj
      obj->Attach(this);
    }
  }    
}

বিকল্প পদ্ধতি হ'ল তৃতীয় শ্রেণি, সি তৈরি করা হবে যা এবি জোড়গুলির স্থির তালিকা পরিচালনা করে।


এবি জোড়গুলির তালিকা পরিচালনা করতে আপনার তৃতীয় শ্রেণির সি থাকার বিকল্প পরামর্শ সম্পর্কিত একটি প্রশ্ন: এ এবং বি এর জুটির সদস্যদের কীভাবে জানতে পারবে? প্রতিটি এ এবং বি এর জন্য (একক) সি এর একটি লিঙ্ক প্রয়োজন, তারপরে সিটিকে উপযুক্ত জোড়গুলি খুঁজতে বলুন? বি :: ফু () {স্টাড :: ভেক্টর <এ *> যেমন = সি গেটএস (এটি); / * হিসাবে যেমন কিছু করুন ... * /} অথবা আপনি কি অন্য কিছু কল্পনা করেছিলেন? কারণ এটি ভয়াবহভাবে সংশ্লেষিত বলে মনে হচ্ছে।
দিমিত্রি শুরালিভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.