ООП дизайн для полиморфной обработки объектов - PullRequest
3 голосов
/ 15 ноября 2011

У меня есть объекты разных типов, полученные из одной базы (например, круг, прямоугольник, многоугольник ... и т. Д.), И у меня есть набор предопределенных операций, которые можно применить к этим объектам (например, перемещение, поворот, копирование ...и так далее). Решение, которое мне нравится в этой ситуации, - шаблон посетителей. У меня есть посетители для каждой операции, которая содержит полный набор операций для всех типов. Это позволяет мне добавлять новые функции к объектам, не меняя сам объект. Операции определенно будут меняться и добавляться чаще, чем новые типы объектов, так что это действительно здорово, но есть одна проблема. Все изложенное выше реализовано в виде библиотеки, которая может быть (и будет) расширяться другими программистами в будущем. Программисты могут добавлять объекты нового типа и реализовывать операции или нет. Например, можно добавить класс «треугольник», который поддерживает перемещение, но не поддерживает вращение. В этом случае программист не сможет расширить моего посетителя для обработки операции перемещения для своего объекта. Я вижу еще одно решение - иметь такие интерфейсы, как i_movable, i_rotatable, i_copyable. Каждый класс реализует один или несколько из этих интерфейсов, затем я проверяю в своей библиотеке, поддерживает ли указанный объект данный интерфейс с dynamic_cast, и применяю операцию. Что-то вроде

if (i_movable* m = dynamic_cast<i_movable>(obj)) m->move(10, 20);

но мне не очень нравится это решение. Кто-нибудь может предложить что-то лучше?

Это может быть не очень важно для проектирования ООП, но язык реализации - C ++, поэтому я ограничен возможностями C ++.

обновление

Если никто не может придумать лучшего решения, не могли бы вы хотя бы оставить голосование за предложенное?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 15 ноября 2011

Если я вас правильно понимаю, если операция не поддерживается, вы ничего не делаете (или, в более общем случае, ведете себя единообразно, независимо от рассматриваемого объекта).Тогда простое решение состоит в том, чтобы обеспечить поведение по умолчанию в базовом классе, а затем, если производный класс не реализует свою собственную версию, поведение по умолчанию автоматически включается без каких-либо дополнительных механизмов.

Если я правильно помнюВ Turbo Vision от Borland такие методы назывались «псевдо абстрактными»: они не являются действительно абстрактными (их не запрещено называть, и нет строгой необходимости переопределять их в производных классах), но они ничего не делают, если не переопределены.*

0 голосов
/ 15 ноября 2011

Вместо этого:

if (i_movable* m = dynamic_cast<i_movable>(obj)) m->move(10, 20);

вы можете использовать некоторые приемы мета-программирования шаблонов (взгляните на boost :: is_base_of ):

#include "boost/type_traits/is_base_of.hpp" 
#include <iostream>

struct i_move
{
    virtual void move(const float, const float ) = 0;
};
struct Triangle
{
    // not movable
};
struct Circle : i_move
{
    virtual void move(const float, const float )
    {
        // move me
    }
};

template< class D >
bool IsMovable( D&)
{
    return boost::is_base_of<i_move,D>::value;
}

int main()
{
    Circle a;
    Triangle b;
    std::cout<<std::boolalpha<<IsMovable(a)<<std::endl;
    std::cout<<std::boolalpha<<IsMovable(b)<<std::endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...