Смекни!
smekni.com

Проектирование классов в шутку и всерьез (стр. 2 из 2)

Прилагательные "стройная" и "зеленая" заменяем на прилагательные "фигурный" и "цветной", отводя им возможность быть уточненным - какая именно фигура и какой именно цвет.

Существительные "лес", "зима", "лето" относим к самостоятельным классам, образованным от базового класса TObject. Существительное "елочка" наследуем от базового класса TObject, от интерфейсов "фигурный" и "цветной", а также добавляем неименованные интерфейсы из отдельных глаголов "родиться" и "рости". Быть может, что при большем объеме исходного текста мы бы пришли к иной схеме классов и выделили бы эти неименованные интерфейсы явно.

Довольно интересным является вопрос о союзе "и". По исходному тексту, функция "быть" возвращает набор из существительных "зима" и "лето". Если отнести эти существительные к разным классам, то получим набор разнотипных данных. Это на мой взгляд некрасиво и лучше провести модификацию схемы классов. Проведем укрупнение классов "зима" и "лето" путем отнесения их к одному классу и различением их признаком "время года". Исходной иерархией является:

classТЗима : publicTObject {};

classTЛето : publicTObjct {};

Результирующей иерархией является укрупненная или агрегированная:

enum ЕВремяГода = { зима, лето};

class ТВремяГода : public TObject

{

public:

ЕВремяГода ВремяГода;

};

Если целевой язык программирования позволяет, то следует определиться со спецификатором константности аргументов, передаваемых по ссылке, и константности функций по признаку - изменяет функция состояние объекта или нет. Если функция не изменяет состояние объекта, то, очевидно, она может быть объявлена константной. Кстати, если в результате проектирования классов мы получим классы с только константными функциями, то смело можно сказать, что исходный текст содержал описание статического состояния объектов. Если же в иерархии полученных классов все функции только константные, то значит схема классов безжизненная. И после этого можно идти обратно к постановщику и громко вопрошать: "И???"

Шаг 5

На этом шаге, кстати, последнем, следует аккуратно, без помарок выписать схему классов на выбранном языке программирования. Здесь уже требуются только аккуратность и знание синтаксиса языка.

В нашем примере может получиться что-то типа:

#include ...

class TЛес : public TObject {};

enum ЕВремяГода { зима, лето};

class ТВремяГода : public TObject

{

public:

const ЕВремяГода GetВремяГода()

{ return ВремяГода};

{};

};

// здесь есть два варианта и второй в том, чтобы объявить

// время года как typedef ЕВремяГода ТВремяГода;

// какой вариант выбрать - дело вкуса.

// я выбрал первый потому, что он позволяет запретить

// изменение времени года для созданного объекта.

typedef vector <ТВремяГода> ВременаГода;

enum Фигура { никакая, стройная};

enum Цвет { никакой, зеленый};

class TФигурный

{

public:

// получение фигуры, зная времена года

const virtual Фигура Быть( ВременаГода& ) = 0;

// получение времени года, зная фигуру

const virtual ВременаГода Быть( Фигура) = 0;

};

class TЦветной

{

public:

// получение цвета, зная времена года

const virtual Цвет Быть( ВременаГода& ) = 0;

// получение времени года, зная Цвет

const virtual ВременаГода Быть( Цвет) = 0;

};

class ТЕлочка

: public TObject,

public ТФигурный,

public ТЦветной

{

public:

constvirtualФигура Быть( ВременаГода& );

const virtual ВременаГода Быть( Цвет);

const ТЛес Родиться();

const ТЛес Рости();

ТЕлочка(); // конструктор вызывается, когда елочка родится

~ТЕлочка();

// деструктор вызывается не тогда, когда елочку срубят,

// а тогда, когда после Нового Года выбросят на помойку

// и бедный дворник должен будет ее сжечь, поскольку

// елки в контейнеры грузить нельзя ;)

};

// получили две функции Быть с одинаковым аргументом.

// подобные проблемы следует решать по правилам применяемого

// языка. В нашем случае придется поменять

// имена функций на менее читабельные.

В примере я хотел сначала писать на Object Pascal. Мысленно разговаривая с читателем, услышал шум и топот ног и выкрики с мест - "А почему не С++?". Подумал и согласился - пусть будет на C++. Конечно же, приведенная метода не есть абсолют. Как говорится, если победишь в бою с нарушением устава - молодец, творчески мыслишь, отбрасывая устаревшие догмы. Если проиграл соблюдая устав - негодяй, который не смог постичь вековые истины. Если данная метода кому поможет - то-то я порадуюсь... Мне лично иногда помогает, особенно когда голова уже ничего не соображает и приходится действовать на автопилоте. Или когда приходится разбираться в исходниках и отгадывать - что же автор хотел сказать. Осуществлять своего рода модный ныне реинжиниринг. Что интересно, потом на свежую голову просмотришь что понаписал и удивляешься своей прозорливости и вообще тому, что это работает.