سؤال

لم أقرأ كتاب التصميم C ++ الحديث ، لكنني وجدت فكرة حقن السلوك من خلال قوالب مثيرة للاهتمام. أحاول الآن تطبيقه بنفسي.

لدي فصل يحتوي على مسجل اعتقدت أنه يمكن حقنه كسياسة. يحتوي المسجل على طريقة log () التي تأخذ std :: string أو std :: wstring اعتمادًا على سياستها:

// basic_logger.hpp
template<class String>
class basic_logger
{
public:
    typedef String string_type;

    void log(const string_type & s) { ... }
};
typedef basic_logger<std::string> logger;
typedef basic_logger<std::wstring> wlogger;

// reader.hpp
template<class Logger = logger>
class reader
{
public:
    typedef Logger logger_type;

    void read()
    {
        _logger.log("Reading...");
    }

private:
    logger_type _logger;
};

الآن السعي هو ، هل يجب أن يأخذ القارئ مسجلًا كوسيطة ، كما هو أعلاه ، أو هل يجب أن يستغرق سلسلة ثم إنشاء إنشاء BASIC_LOGGER كمتغير مثيل؟ مثل ذلك:

template<class String>
class reader
{
public:
    typedef String string_type;
    typedef basic_logger<string_type> logger_type;

    // ...

private:
    logger_type _logger;
};

ما هي الطريقة الصحيحة للذهاب؟

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

المحلول

لاستخدام فئة السياسة فعليًا ، يجب أن تكون السياسة معلمة قالب. أحد الأمثلة على ذلك هو معلمة char_traits إلى basic_string ، على الرغم من أن ذلك يتم تنفيذه بشكل مختلف عن سياسات MC ++ d ، والتي تستخدم الميراث للاستفادة من تحسين الفئة الأساسية الفارغة والسماح بإضافة سهلة إلى الواجهة العامة للفئة (بطريقة أفضل بكثير من لف كل طريقة ممكنة ؛ مرة أخرى ، اقرأ MC ++ D). لا يزال بإمكانك تقديم افتراضي:

template<class String, class Logger=basic_logger<String> >
struct reader : Logger {
  void read() {
    this->log("Reading...");
  }
};

نصائح أخرى

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

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

السياسات عادة ما تكون معلمات تؤثر على سلوك الطبقة.

من الصعب للغاية استخراج السياسات من الفصل ، وكلما زادت صعوبة أن السياسات تحتاج إلى تغطية المفاهيم المتعامدة حتى تتمكن من تغيير السياسات دون التأثير على الآخرين ... وهو أمر صعب للغاية كما يمكنك أن تتخيل.

إذا كنت ترغب في رؤية مثال جيد على استخدام السياسة ، فابحث Loki::Singleton وهو ما يظهر بالكامل في الكتاب.

template
<
  typename T,
  template <class> class CreationPolicy = CreateUsingNew,
  template <class> class LifetimePolicy = DefaultLifetime,
  template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
  class MutexPolicy = LOKI_DEFAULT_MUTEX
>
class SingletonHolder;

مثير للإعجاب ، أليس كذلك؟

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

حسنًا ، الآن يجب أن أعترف أنني لست مريحًا تمامًا مع فكرة طلب الفصل مع عدد محدد من معلمات القالب ، كنت شخصياً كنت أفضل شيئًا على طول:

template
<
  class T,
  class CreationPolicy = CreateUsingNew<T>,
  class LifetimePolicy = DefaultLifeTime<T>,
  class MutexPolicy = LOKI_DEFAULT_MUTEX,
  template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL
>
class SingletonHolder;

لا يمكن مساعدته الأخيرة حقًا ، فمن المفترض أن تمررها SingletonHolder الطبقة نفسها.

ومع ذلك ، أجد أنه من الأسهل تبادل السياسات هنا ، فإنه يسمح لي بتحديد سياسات مثل:

template <class T, size_t Param> MyCreationPolicy;

واستخدم مباشرة دون الاضطرار إلى لفه لقيمة معينة من param بحيث يطابق التوقيع.

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