سؤال

عند تنفيذ البحث عن إبرة في كومة قش بطريقة موجهة للكائنات، يكون لديك ثلاثة بدائل:

1. needle.find(haystack)

2. haystack.find(needle)

3. searcher.find(needle, haystack)

أيهم تفضل ولماذا؟

أعلم أن بعض الأشخاص يفضلون البديل الثاني لأنه يتجنب تقديم كائن ثالث.ومع ذلك، لا يسعني إلا أن أشعر أن النهج الثالث هو "الصحيح" من الناحية المفاهيمية، على الأقل إذا كان هدفك هو نمذجة "العالم الحقيقي".

في أي الحالات تعتقد أنه من المبرر تقديم كائنات مساعدة، مثل الباحث في هذا المثال، ومتى يجب تجنبها؟

هل كانت مفيدة؟

المحلول

عادةً ما يجب تطبيق الإجراءات على ما تقوم به الإجراء ...في هذه الحالة كومة القش، لذلك أعتقد أن الخيار 2 هو الأنسب.

لديك أيضًا بديل رابع أعتقد أنه سيكون أفضل من البديل 3:

haystack.find(needle, searcher)

في هذه الحالة، يسمح لك بتوفير الطريقة التي تريد البحث بها كجزء من الإجراء، وبالتالي يمكنك الاحتفاظ بالإجراء مع الكائن الذي يتم تشغيله عليه.

نصائح أخرى

من بين الثلاثة، أفضّل الخيار رقم 3.

ال مبدأ المسؤولية الفردية يجعلني لا أرغب في وضع إمكانات البحث على DTOs أو النماذج الخاصة بي.مسؤوليتهم هي أن يكونوا بيانات، لا أن يجدوا أنفسهم، ولا ينبغي أن تعرف الإبر عن أكوام القش، ولا ينبغي أن تعرف أكوام التبن عن الإبر.

بالنسبة لما يستحقه الأمر، أعتقد أن معظم ممارسي OO يستغرقون وقتًا طويلاً لفهم سبب كون الخيار رقم 3 هو الخيار الأفضل.لقد قمت بـ OO لمدة عقد من الزمن، على الأرجح، قبل أن أزعجها حقًا.

@wilhelmtell، تعد لغة C++ واحدة من اللغات القليلة جدًا التي تتميز بتخصص القالب الذي يجعل مثل هذا النظام يعمل بالفعل.بالنسبة لمعظم اللغات، قد تكون طريقة "البحث" للأغراض العامة فكرة سيئة للغاية.

هناك بديل آخر، وهو النهج الذي تستخدمه STL لـ C++:

find(haystack.begin(), haystack.end(), needle)

أعتقد أنه مثال رائع على الصراخ C ++ "في وجهك!" إلى OOP.الفكرة هي أن OOP ليس حلاً سحريًا من أي نوع؛في بعض الأحيان يكون أفضل وصف للأشياء من حيث الأفعال، وأحيانًا من حيث الأشياء، وأحيانًا لا يتم وصف أي منهما على حد سواء، وأحيانًا كليهما معًا.

قال Bjarne Stroustrup في TC++PL أنه عند تصميم نظام ما، يجب أن تسعى جاهداً لتعكس الواقع في ظل قيود التعليمات البرمجية الفعالة والفعالة.بالنسبة لي، هذا يعني أنه لا ينبغي عليك أبدًا اتباع أي شيء بشكل أعمى.فكر في الأشياء الموجودة في متناول اليد (كومة قش، إبرة) والسياق الذي نحن فيه (نبحث، هذا هو ما يدور حوله التعبير).

إذا كان التركيز على البحث، فسيتم استخدام خوارزمية (إجراء) تؤكد على البحث (أي البحث).بمرونة لتناسب أكوام التبن والمحيطات والصحاري والقوائم المرتبطة).إذا كان التركيز على كومة القش، فقم بتغليف طريقة البحث داخل كائن كومة القش، وهكذا.

ومع ذلك، في بعض الأحيان تكون في شك وتواجه صعوبة في الاختيار.في هذه الحالة، كن موجهًا للكائنات.إذا غيرت رأيك لاحقًا، أعتقد أنه من الأسهل استخراج إجراء من كائن ثم تقسيم الإجراء إلى كائنات وفئات.

اتبع هذه الإرشادات، وسيكون الكود الخاص بك أكثر وضوحًا وأكثر جمالًا.

أود أن أقول أن الخيار رقم 1 قد انتهى تمامًا.يجب أن تتم قراءة الكود بطريقة تخبرك بما يفعله.الخيار الأول يجعلني أعتقد أن هذه الإبرة ستبحث لي عن كومة قش.

يبدو الخيار 2 جيدًا إذا كان من المفترض أن تحتوي كومة القش على إبر.ستحتوي ListCollections دائمًا على ListItems، لذا فإن القيام بـ Collection.find(item) أمر طبيعي ومعبر.

أعتقد أن إدخال كائن مساعد يكون مناسبًا عندما:

  1. لا يمكنك التحكم في تنفيذ الكائنات المعنية
    أي:search.find(ObsecureOSObject، ملف)
  2. لا توجد علاقة منتظمة أو معقولة بين الكائنات
    أي:nameMatcher.find(منازل,أشجار.اسم)

أنا مع براد في هذا الأمر.كلما عملت على أنظمة معقدة للغاية، كلما رأيت الحاجة إلى فصل الأشياء بشكل حقيقي.إنه على حق.من الواضح أن الإبرة لا ينبغي أن تعرف أي شيء عن كومة القش، لذا فإن 1 قد خرج بالتأكيد.لكن كومة القش لا ينبغي أن تعرف شيئًا عن الإبرة.

إذا كنت أقوم بتصميم كومة قش، فقد أقوم بتنفيذها كمجموعة - ولكن كمجموعة من القش أو قَشَّة - ليست مجموعة من الإبر!ومع ذلك، أود أن آخذ في الاعتبار أن الأشياء تضيع في كومة قش، لكنني لا أعرف شيئًا عن ماهية هذه الأشياء بالضبط.أعتقد أنه من الأفضل عدم جعل كومة القش تبحث عن عناصر في حد ذاتها (كيف ذكي هو كومة قش على أي حال).النهج الصحيح بالنسبة لي هو أن أجعل كومة القش تقدم مجموعة من الأشياء الموجودة فيها، ولكنها ليست قشًا أو تبنًا أو أي شيء يمنح كومة القش جوهرها.

class Haystack : ISearchableThingsOnAFarm {
   ICollection<Hay> myHay;
   ICollection<IStuffSmallEnoughToBeLostInAHaystack> stuffLostInMe;

   public ICollection<Hay> Hay {
      get {
         return myHay;
      }
   }

   public ICollection<IStuffSmallEnoughToBeLostInAHayStack> LostAndFound {
      get {
        return stuffLostInMe;
      }
   }
}

class Needle : IStuffSmallEnoughToBeLostInAHaystack {
}

class Farmer {
  Search(Haystack haystack, 
                 IStuffSmallEnoughToBeLostInAHaystack itemToFind)
}

في الواقع، كنت سأقوم بكتابة المزيد وتجريده في الواجهات ثم أدركت مدى الجنون الذي كنت أشعر به.شعرت وكأنني كنت في صف علوم الكمبيوتر في الكلية.:ص

انت وجدت الفكرة.أعتقد أن الترابط بشكل فضفاض قدر الإمكان هو أمر جيد، ولكن ربما كنت أبتعد قليلاً!:)

إذا كان كل من Needle وHaystack من المنظمات اللامركزية المستقلة، فإن الخيارين 1 و2 غير واردين.

والسبب في ذلك هو أن المنظمات اللامركزية المستقلة يجب أن تكون مسؤولة فقط عن الاحتفاظ بخصائص كائنات العالم الحقيقي التي تقوم بتصميمها، ويجب أن يكون لديها فقط أساليب getter وsetter (أو مجرد الوصول المباشر إلى الملكية).وهذا يجعل إجراء تسلسل لـ DAOs إلى ملف، أو إنشاء طرق لنسخة عامة/مقارنة عامة أسهل في الكتابة، حيث لن يحتوي الكود على مجموعة كاملة من عبارات "if" لتخطي هذه الأساليب المساعدة.

هذا يترك فقط الخيار 3، والذي يتفق معظم الناس على أنه السلوك الصحيح.

يتمتع الخيار 3 ببعض المزايا، والميزة الأكبر هي اختبار الوحدة.وذلك لأنه يمكن الاستهزاء بسهولة بكائنات Needle وHaystack، بينما إذا تم استخدام الخيار 1 أو 2، فسيتعين تعديل الحالة الداخلية لأي من Needle أو Haystack قبل إجراء البحث.

ثانيًا، مع وجود الباحث الآن في فئة منفصلة، ​​يمكن الاحتفاظ بجميع أكواد البحث في مكان واحد، بما في ذلك كود البحث المشترك.بينما إذا تم وضع كود البحث في DAO، فسيتم تخزين كود البحث الشائع إما في تسلسل هرمي معقد للفئات، أو مع فئة مساعد البحث على أي حال.

وهذا يعتمد كليًا على ما يختلف وما يبقى على حاله.

على سبيل المثال، أنا أعمل على (غير OOP) نطاق حيث تختلف خوارزمية البحث اعتمادًا على نوع الإبرة وكومة القش.بصرف النظر عن حقيقة أن هذا سيتطلب إرسالًا مزدوجًا في بيئة موجهة للكائنات، فهذا يعني أيضًا أنه ليس من المفيد الكتابة أيضًا needle.find(haystack) أو للكتابة haystack.find(needle).

من ناحية أخرى، يمكن لتطبيقك أن يفوض عملية البحث إلى أي من الفئتين، أو يلتزم بخوارزمية واحدة تمامًا وفي هذه الحالة يكون القرار تعسفيًا.في هذه الحالة، أفضّل haystack.find(needle) الطريقة لأنه يبدو أكثر منطقية تطبيق النتائج على كومة القش.

عند تنفيذ بحث إبرة عن كومة قش بطريقة موجهة نحو الكائن ، يكون لديك بشكل أساسي ثلاثة بدائل:

  1. إبرة البحث عن (كومة قش)

  2. كومة قش.العثور على (إبرة)

  3. searcher.find (إبرة، كومة قش)

أيهم تفضل ولماذا؟

تصحيح لي إذا كنت مخطئا، ولكن في جميع الأمثلة الثلاثة بالفعل يملك إشارة إلى الإبرة التي تبحث عنها، أليس هذا مثل البحث عن نظارتك عندما تكون على أنفك؟:ص

بغض النظر عن التورية، أعتقد أن الأمر يعتمد حقًا على ما تعتبره مسؤولية كومة القش ضمن المجال المحدد.هل نهتم بها فقط بمعنى كونها شيئًا يحتوي على إبر (مجموعة، بشكل أساسي)؟ثم Haystack.find(needlePredicate) جيد.بخلاف ذلك، قد يكون FarmBoy.find(predicate, haystack) أكثر ملاءمة.

على حد تعبير المؤلفين العظماء سيكب,

يجب أن تكون البرامج مكتوبة ليقرأها الناس، ولا يمكن للآلات أن تنفذها إلا بالصدفة

أفضّل أن تكون كلتا الطريقتين 1 و 2 في متناول اليد.باستخدام روبي كمثال، يأتي مع .include? الذي يستخدم مثل هذا

haystack.include? needle
=> returns true if the haystack includes the needle

رغم ذلك، في بعض الأحيان، ولأسباب تتعلق بقابلية القراءة فقط، أرغب في قلب الأمر رأسًا على عقب.روبي لا يأتي مع in? الطريقة، ولكنها عبارة عن بطانة واحدة، لذلك غالبًا ما أفعل هذا:

needle.in? haystack
=> exactly the same as above

إذا كان "الأهم" التركيز على كومة القش، أو عملية البحث، فأنا أفضل الكتابة include?.رغم ذلك، في كثير من الأحيان، لا يهمك حقًا كومة القش أو البحث، بل مجرد أن الكائن موجود - في هذه الحالة أجد in? ينقل معنى البرنامج بشكل أفضل.

ذلك يعتمد على الاحتياجات الخاصة بك.

على سبيل المثال، إذا كنت لا تهتم بخصائص الباحث (على سبيل المثال،قوة الباحث، والرؤية، وما إلى ذلك)، ثم أود أن أقول إن haystack.find(needle) سيكون الحل الأنظف.

ولكن، إذا كنت تهتم بخصائص الباحث (أو أي خصائص أخرى في هذا الشأن)، فسأقوم بإدخال واجهة ISearcher إما في مُنشئ كومة القش أو الوظيفة لتسهيل ذلك.وهذا يدعم كلاً من التصميم الموجه للكائنات (يحتوي كومة القش على إبر) وعكس حقن التحكم/التبعية (يسهل اختبار الوحدة لوظيفة "البحث").

يمكنني التفكير في المواقف التي يكون فيها أي من النكهات الأولين منطقيًا:

  1. إذا كانت الإبرة تحتاج إلى معالجة مسبقة، كما هو الحال في خوارزمية كنوث-موريس-برات، needle.findIn(haystack) (أو pattern.findIn(text)) أمر منطقي، لأن كائن الإبرة يحمل الجداول الوسيطة التي تم إنشاؤها لكي تعمل الخوارزمية بفعالية

  2. إذا كانت كومة القش تحتاج إلى معالجة مسبقة، كما هو الحال في المحاولة، فإن haystack.find(needle) (أو words.hasAWordWithPrefix(prefix)) يعمل بشكل أفضل.

وفي كلتا الحالتين أعلاه يكون أحد الإبرة أو كومة القش على علم بالبحث.كما أن كلاهما على علم ببعضهما البعض.إذا كنت تريد ألا تكون الإبرة وكومة القش على علم ببعضهما البعض أو بالبحث، searcher.find(needle, haystack) سيكون من المناسب.

سهل:احرق كومة القش!وبعد ذلك ستبقى الإبرة فقط.يمكنك أيضًا تجربة المغناطيس.

سؤال أصعب:كيف تجد إبرة معينة في مجموعة من الإبر؟

إجابة:قم بربط كل واحدة منها ثم قم بإرفاق الطرف الآخر من كل خيط من الخيوط بفهرس تم فرزه (أي.مؤشرات)

يجب أن تعتمد الإجابة على هذا السؤال في الواقع على المجال الذي يتم تنفيذ الحل من أجله.
إذا حدث لك محاكاة بحث مادي في كومة قش مادية، فقد يكون لديك الفصول الدراسية

  • فضاء
  • قَشَّة
  • إبرة
  • الباحث

فضاء
يعرف الكائنات الموجودة في أي الإحداثيات
ينفذ قوانين الطبيعة (يحول الطاقة، ويكتشف الاصطدامات، وما إلى ذلك)

إبرة, قَشَّة
تقع في الفضاء
الرد على القوات

الباحث
يتفاعل مع الفضاء:
    يحرك يده، ويطبق المجال المغناطيسي، ويحرق التبن، ويطبق الأشعة السينية، ويبحث عن الإبرة...

هكذاseeker.find(needle, space) أو seeker.find(needle, space, strategy)

تصادف وجود كومة القش في المكان الذي تبحث فيه عن الإبرة.عندما تقوم بتجريد المساحة كنوع من الآلة الافتراضية (فكر في:المصفوفة) يمكنك الحصول على ما ورد أعلاه باستخدام كومة قش بدلاً من المساحة (الحل 3/3ب):

seeker.find(needle, haystack) أو seeker.find(needle, haystack, strategy)

لكن المصفوفة كانت هي المجال، الذي يجب استبداله فقط بكومة قش، إذا كانت إبرتك لا يمكن أن تكون في أي مكان آخر.

ومرة أخرى، كان الأمر مجرد تشبيه.ومن المثير للاهتمام أن هذا يفتح العقل لاتجاهات جديدة تمامًا:
1.لماذا فقدت الإبرة في المقام الأول؟هل يمكنك تغيير العملية حتى لا تفقدها؟
2.هل يتعين عليك العثور على الإبرة المفقودة أم يمكنك ببساطة الحصول على إبرة أخرى ونسيان الأولى؟(يفضل لو أن الإبرة تذوب بعد فترة)
3.إذا فقدت إبرك بانتظام وتحتاج إلى العثور عليها مرة أخرى، فقد ترغب في ذلك

  • اصنع إبرًا قادرة على العثور على نفسها، على سبيل المثال.يسألون أنفسهم بانتظام:هل أنا ضائع؟إذا كانت الإجابة بنعم، فإنهم يرسلون موقعهم المحسوب بواسطة نظام تحديد المواقع العالمي (GPS) إلى شخص ما أو يبدأون في إصدار صوت تنبيه أو أي شيء آخر:
    needle.find(space) أو needle.find(haystack)    (الحل 1)

  • قم بتثبيت كومة قش مع كاميرا على كل قشة، وبعد ذلك يمكنك أن تسأل عقل خلية كومة القش عما إذا كان قد رأى الإبرة مؤخرًا:
    كومة قش.العثور على (إبرة) (الحل 2)

  • أرفق علامات RFID بإبرك، حتى تتمكن من تثليثها بسهولة

كل هذا فقط لأقول ذلك في التنفيذ الخاص بك أنت جعل الإبرة وكومة القش وفي معظم الأحيان المصفوفة على مستوى ما.

لذا قرر وفقًا لنطاقك:

  • هل الغرض من كومة القش أن تحتوي على الإبر؟ثم انتقل إلى الحل 2.
  • هل من الطبيعي أن تضيع الإبرة في أي مكان؟ثم انتقل إلى الحل 1.
  • هل تضيع الإبرة في كومة القش بالصدفة؟ثم انتقل إلى الحل 3.(أو فكر في استراتيجية استرداد أخرى)

haystack.find(needle)، ولكن يجب أن يكون هناك حقل للبحث.

أعلم أن حقن التبعية هو أمر شائع، لذلك لا يفاجئني أن @Mike Stone's haystack.find(needle, searcher) قد تم قبوله.لكني لا أوافق:يبدو لي أن اختيار ما يستخدمه الباحث هو قرار كومة القش.

فكر في اثنين من الباحثين:يتكرر برنامج البحث المغناطيسي على مستوى الصوت، ويحرك المغناطيس ويحركه بطريقة تتفق مع قوة المغناطيس.يقوم QuickSortSearcher بتقسيم المكدس إلى قسمين حتى تظهر الإبرة في إحدى الأكوام الفرعية.قد يعتمد الاختيار الصحيح للباحث على حجم كومة القش (بالنسبة للمجال المغناطيسي، على سبيل المثال)، وكيفية دخول الإبرة إلى كومة القش (أي، هل موضع الإبرة عشوائي حقًا أم أنه متحيز؟)، وما إلى ذلك.

إذا كان لديك Haystack.find (الإبرة ، الباحث) ، فأنت تقول "اختيار أفضل ما هو أفضل استراتيجية بحث خارج سياق كومة القش." لا أعتقد أن هذا من المحتمل أن يكون صحيحًا.أعتقد أنه من الأرجح أن "كومة القش تعرف أفضل طريقة للبحث عن أنفسهم". أضف Setter ولا يزال بإمكانك حقن الباحث يدويًا إذا كنت بحاجة إلى تجاوز أو للاختبار.

أنا شخصياً أحب الطريقة الثانية.السبب وراء ذلك هو أن واجهات برمجة التطبيقات الرئيسية التي عملت معها تستخدم هذا الأسلوب، وأجده منطقيًا للغاية.

إذا كانت لديك قائمة بالأشياء (كومة قش) لبحثت عن (find()) الإبرة.

@ بيتر ماير

انت وجدت الفكرة.أعتقد أن الترابط بشكل فضفاض قدر الإمكان هو أمر جيد، ولكن ربما كنت أبتعد قليلاً!:)

يخطئ...نعم...اعتقد ان IStuffSmallEnoughToBeLostInAHaystack نوع من العلم الأحمر :-)

لديك أيضًا بديل رابع أعتقد أنه سيكون أفضل من البديل 3:

haystack.find(needle, searcher)

أرى وجهة نظرك، ولكن ماذا لو searcher ينفذ واجهة بحث تسمح بالبحث في أنواع أخرى من الكائنات غير أكوام القش، والعثور على أشياء أخرى غير الإبر فيها؟

يمكن أيضًا تنفيذ الواجهة باستخدام خوارزميات مختلفة، على سبيل المثال:

binary_searcher.find(needle, haystack)
vision_searcher.find(pitchfork, haystack)
brute_force_searcher.find(money, wallet)

ولكن، كما أشار آخرون بالفعل، أعتقد أيضًا أن هذا مفيد فقط إذا كان لديك بالفعل خوارزميات بحث متعددة أو فئات متعددة يمكن البحث فيها أو العثور عليها.إذا لم يكن الأمر كذلك، فأنا أوافق haystack.find(needle) أفضل بسبب بساطته، لذلك أنا على استعداد للتضحية ببعض "الصواب" من أجله.

class Haystack {//whatever
 };
class Needle {//whatever
 }:
class Searcher {
   virtual void find() = 0;
};

class HaystackSearcher::public Searcher {
public:
   HaystackSearcher(Haystack, object)
   virtual void find();
};

Haystack H;
Needle N;
HaystackSearcher HS(H, N);
HS.find();

مزيج من 2 و 3، حقا.

بعض أكوام التبن ليس لديها استراتيجية بحث متخصصة؛مثال على ذلك هو مجموعة.الطريقة الوحيدة للعثور على شيء ما هي البدء من البداية واختبار كل عنصر حتى تجد العنصر الذي تريده.

بالنسبة لهذا النوع من الأشياء، ربما تكون الوظيفة المجانية هي الأفضل (مثل C++).

قد يكون لبعض أكوام التبن استراتيجية بحث متخصصة مفروضة عليها.يمكن فرز المصفوفة، مما يسمح لك باستخدام البحث الثنائي، على سبيل المثال.وظيفة حرة (أو زوج من الوظائف الحرة، على سبيل المثال.النوع وbinary_search) ربما يكون الخيار الأفضل.

تحتوي بعض أكوام القش على استراتيجية بحث متكاملة كجزء من تنفيذها؛على سبيل المثال، تقوم الحاويات الترابطية (المجموعات والخرائط المجزأة أو المرتبة) بذلك.في هذه الحالة، من المحتمل أن يكون البحث طريقة بحث أساسية، لذلك من المحتمل أن يكون طريقة، على سبيل المثال.كومة قش. العثور على (إبرة).

يمكن أن يحتوي Haystack على أشياء واحدة من الأشياء التي يتم اكتشاف Needle هي شيء مسؤول عن البحث عن الأشياء يمكن أن يقبل كومة من الأشياء كمصدر لمكان العثور على شيء يمكن أن يقبل أيضًا وصفًا للأشياء التي يحتاجها إلى العثور عليها

لذلك، من الأفضل، للحصول على حل مرن، أن تفعل شيئًا مثل:واجهة الاشياء

Haystack = ilistu003CIStuff> الإبرة:IStuff

الباحث.u003CIStuff> Stuffstolookin)

في هذه الحالة، لن يتم ربط الحل الخاص بك بالإبرة وكومة القش فقط، ولكنه قابل للاستخدام لأي نوع يقوم بتنفيذ الواجهة

لذا، إذا كنت تريد العثور على سمكة في المحيط، فيمكنك ذلك.

نتائج فار = Finder.Find(fish, Ocean)

إذا كان لديك إشارة إلى كائن الإبرة لماذا تبحث عنه؟:) يخبرك مجال المشكلة ومقاعد الاستخدام أنك لا تحتاج إلى وضع دقيق للإبرة في كومة قش (مثل ما يمكنك الحصول عليه من list.indexof (العنصر)) ، فأنت بحاجة فقط إلى إبرة.وليس لديك بعد.لذا فإن إجابتي هي شيء من هذا القبيل

Needle needle = (Needle)haystack.searchByName("needle");

أو

Needle needle = (Needle)haystack.searchWithFilter(new Filter(){
    public boolean isWhatYouNeed(Object obj)
    {
        return obj instanceof Needle;
    }
});

أو

Needle needle = (Needle)haystack.searchByPattern(Size.SMALL, 
                                                 Sharpness.SHARP, 
                                                 Material.METAL);

أوافق على أن هناك المزيد من الحلول الممكنة التي تعتمد على استراتيجيات بحث مختلفة، لذلك فهي تقدم الباحث.لقد كانت هناك تعليقات كافية على هذا الأمر، لذلك لا أهتم به هنا.وجهة نظري هي أن الحلول المذكورة أعلاه تنسى حالات الاستخدام - ما الفائدة من البحث عن شيء ما إذا كان لديك بالفعل إشارة إليه؟في حالة الاستخدام الأكثر طبيعية، لا يكون لديك إبرة بعد، لذلك لا تستخدم إبرة متغيرة.

يشير براد ويلسون إلى أن الأشياء يجب أن تتحمل مسؤولية واحدة.في الحالة القصوى، يكون للكائن مسؤولية واحدة وليس له حالة.ومن ثم يمكن أن يصبح...وظيفة.

needle = findNeedleIn(haystack);

أو يمكنك كتابتها هكذا:

SynchronizedHaystackSearcherProxyFactory proxyFactory =
    SynchronizedHaystackSearcherProxyFactory.getInstance();
StrategyBasedHaystackSearcher searcher =
    new BasicStrategyBasedHaystackSearcher(
        NeedleSeekingStrategies.getMethodicalInstance());
SynchronizedHaystackSearcherProxy proxy =
    proxyFactory.createSynchronizedHaystackSearcherProxy(searcher);
SearchableHaystackAdapter searchableHaystack =
    new SearchableHaystackAdapter(haystack);
FindableSearchResultObject foundObject = null;
while (!HaystackSearcherUtil.isNeedleObject(foundObject)) {
    try {
        foundObject = proxy.find(searchableHaystack);
    } catch (GruesomeInjuryException exc) {
        returnPitchforkToShed();  // sigh, i hate it when this happens
        HaystackSearcherUtil.cleanUp(hay); // XXX fixme not really thread-safe,
                                           // but we can't just leave this mess
        HaystackSearcherUtil.cleanup(exc.getGruesomeMess()); // bug 510000884
        throw exc; // caller will catch this and get us to a hospital,
                   // if it's not already too late
    }
}
return (Needle) BarnyardObjectProtocolUtil.createSynchronizedFindableSearchResultObjectProxyAdapterUnwrapperForToolInterfaceName(SimpleToolInterfaces.NEEDLE_INTERFACE_NAME).adapt(foundObject.getAdaptable());

لا ينبغي لكومة القش أن تعرف أمر الإبرة، ولا ينبغي للإبرة أن تعرف أمر كومة القش.يحتاج الباحث إلى معرفة كليهما، ولكن ما إذا كان يجب على كومة القش أن تعرف كيفية البحث بنفسها أم لا هي نقطة الخلاف الحقيقية.

لذا سأختار مزيجًا من 2 و3؛يجب أن تكون كومة القش قادرة على إخبار شخص آخر بكيفية البحث فيها، ويجب أن يكون الباحث قادرًا على استخدام تلك المعلومات للبحث في كومة القش.

haystack.magnet().filter(needle);

هل يحاول الكود العثور على إبرة محددة أم أي إبرة فقط؟قد يبدو هذا سؤالًا غبيًا، لكنه يغير المشكلة.

إذا كنت تبحث عن إبرة محددة فإن الكود الموجود في السؤال منطقي.أبحث عن أي إبرة سيكون أشبه

needle = haystack.findNeedle()

أو

needle = searcher.findNeedle(haystack)

وفي كلتا الحالتين، أفضل أن يكون لدي باحث في تلك الفئة.كومة قش لا تعرف كيف تبحث.من منظور CS، فهو مجرد مخزن بيانات يحتوي على الكثير من الأشياء التي لا تريدها.

بالتأكيد الثالث، IMHO.

إن مسألة الإبرة في كومة قش هي مثال لمحاولة العثور على كائن واحد في مجموعة كبيرة من الأشياء الأخرى، مما يشير إلى أنها ستحتاج إلى خوارزمية بحث معقدة (ربما تتضمن مغناطيسًا أو (على الأرجح) عمليات فرعية) ولا تفعل ذلك ليس من المنطقي أن يُتوقع من كومة قش أن تقوم بإدارة سلسلة المحادثات أو تنفيذ عمليات بحث معقدة.

ومع ذلك، فإن كائن البحث مخصص للبحث ومن المتوقع أن يعرف كيفية إدارة سلاسل الرسائل الفرعية لإجراء بحث ثنائي سريع، أو استخدام خصائص العنصر الذي تم البحث عنه لتضييق المنطقة (على سبيل المثال:مغناطيس للعثور على العناصر الحديدية).

هناك طريقة أخرى ممكنة تتمثل في إنشاء واجهتين للكائن القابل للبحث، على سبيل المثال.كومة قش وكائن ToBeSearched على سبيل المثال.إبرة.لذلك، يمكن أن يتم ذلك بهذه الطريقة

public Interface IToBeSearched
{}

public Interface ISearchable
{

    public void Find(IToBeSearched a);

}

Class Needle Implements IToBeSearched
{}

Class Haystack Implements ISearchable
{

    public void Find(IToBeSearched needle)

   {

   //Here goes the original coding of find function

   }

}
haystack.iterator.findFirst(/* pass here a predicate returning
                               true if its argument is a needle that we want */)

iterator يمكن أن تكون واجهة لأي مجموعة غير قابلة للتغيير، مع وجود مجموعات مشتركة findFirst(fun: T => Boolean) طريقة القيام بهذه المهمة.طالما أن كومة القش غير قابلة للتغيير، فلا داعي لإخفاء أي بيانات مفيدة من "الخارج".وبطبيعة الحال، ليس من الجيد ربط تنفيذ مجموعة مخصصة غير تافهة وبعض الأشياء الأخرى التي لديها haystack.فرق تسد، حسنًا؟

في معظم الحالات، أفضل أن أكون قادرًا على تنفيذ عمليات مساعدة بسيطة مثل هذه على الكائن الأساسي، ولكن اعتمادًا على اللغة، قد لا يتوفر للكائن المعني طريقة كافية أو معقولة.

حتى في لغات مثل جافا سكريبت) التي تسمح لك بزيادة/توسيع الكائنات المضمنة، أجد أنه يمكن أن يكون مناسبًا ومثيرًا للمشاكل (على سبيل المثال.إذا كان الإصدار المستقبلي من اللغة يقدم طريقة أكثر كفاءة يتم تجاوزها بواسطة طريقة مخصصة).

هذا المقال يقوم بعمل جيد في تحديد مثل هذه السيناريوهات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top