Паттерн Property

      Комментарии к записи Паттерн Property отключены

Помечено: , ,

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 4 мес., 2 нед. назад.

  • Автор
    Сообщения
  • #3621

    Цель паттерна Property — привязать какую-то функциональность к присваиванию и получению значения какого-либо члена класса. Например, пусть у вас есть класс window, и в нем есть член title. Вы хотите, чтобы в момент присваивания этому члену какого-то значения автоматически вызывалась API функция, которая устанавливала бы текст заголовка окна.

    #include <windows.h>
    #include <iostream>
    
    template <class object, class type>
    class property
    {
    public:
    
        typedef type (object::*get_proc)() const;
        typedef void (object::*set_proc)(type const&);
    
        property(object& object, get_proc getpr, set_proc setpr)
        : obj   (object)
        , getter(getpr)
        , setter(setpr)
        {
        }
    
        operator type ()
        {
            return get();
        }
    
        type const& operator = (type const& value)
        {
            set(value);
            return value;
        }
    
        property& operator = (property const& prt)
        {
            set(prt.get());
            return *this;
        }
    
    private:
    
        object& obj;
        get_proc getter;
        set_proc setter;
    
        inline type get() const
        {
            return (obj.*getter)();
        }
    
        inline void set(type const& value)
        {
            (obj.*setter)(value);
        }
    };
    
    class window
    {
    public:
    
        property<window, std::string> title;
    
        window(std::string const& title_text)
        : title(*this, &window::get_title, &window::set_title)
        {
            // Как-то инициализируем handle
            set_title(title_text);
        }
    
    private:
    
        HWND handle;
    
        std::string get_title() const
        {
            char buffer[1024] = {0};
            GetWindowTextA(handle, buffer, sizeof(buffer));
            return buffer;
        }
    
        void set_title(const std::string& new_title)
        {
            SetWindowTextA(handle, new_title.c_str());
        }
    };
    
    int main()
    {
        window w1("Toolbar");
        window w2("About box");
    
        w1.title = "Help page";
    
        std::string title = w2.title;
    
        w2.title = w1.title;
    
        return 0;
    }

    Паттерн «Property» является далеко не самым привычным и естественным паттерном для языка C++. Например, прямое присваивание (строка 91), и присваивание через агрегирующий класс (строка 93), очевидно, должны иметь различный результат. В первом случае мы ожидаем вызова соответствующих геттера и сеттера, во втором же мы хотим чтобы было выполнено полноценное присваивание с подменой ссылки на объект, которым управляет propetry. Очевидно, что C++ не различает эти два типа присваивания.

    Шаблон проектирования Property хорошо уживается в языках с более ярковыраженными динамическими свойствами, такими как Java или C#. В языке C++ следует стараться использовать альтернативные приемы, поскольку данный паттерн не является естественным для языка и не может быть реализован полностью в соответствии со своей семантикой.

Для ответа в этой теме необходимо авторизоваться.