Я думаю, что есть несколько способов взглянуть на это:
1) Month
- это перечислимый тип с 12 элементами, представляющими свойства 12 месяцев григорианского календаря. Поскольку C ++ явно не предлагает перечислимые типы классов, мы подделаем его либо:
частные конструкторы и открытый доступ к экземплярам (массив, статические члены данных, глобальные переменные или функции (и), которые принимают номер или имя месяца и возвращают указатель / ссылку). Это модифицированный синглтон.
публичные конструкторы, которые проверяют имя или номер месяца и заполняют количество дней из внутренних знаний, имеющихся в классе. Это дает семантику значения класса.
Обратите внимание, что для этой цели модифицированный синглтон (12-тонный) на самом деле не может быть правильным Вы говорите в своем заголовке «могут существовать только определенные предопределенные объекты», но в своем коде вы пишете Month m = GetRandomMonth();
, который создает новый Month
объект с именем m
. Так что есть не только определенные предопределенные объекты, вы создаете один прямо здесь. Похоже, вы хотите использовать месяцы по значению, а не только по ссылке на предопределенные объекты.
Для этого вам нужно Month
, чтобы иметь доступный конструктор копирования, и вам, вероятно, также понадобится оператор присваивания. Это означает, что это не Twelveleton (то есть, ограничено 12 объектами типа), просто есть только 12 возможных различных, не равных значений . Рассмотрим по аналогии тип char
- есть только 256 возможных значений (в моей реализации), но я могу легко создать более 256 объектов: char x[257] = {0};
.
2) Month
- это общий тип, представляющий месяц. В григорианском календаре есть только 12 значений этого типа , фактически используемых (13, если вы используете другое значение для февраля в високосных годах), но если вы хотите создать Month("Jabruapril", 42)
(вымышленный), или Month("Nisan", 30)
(иврит), или Month("December", 30)
(римский календарь до юлианской реформы), потому что вы думаете, что определенные свойства класса помогут вам в том, что вы делаете, тогда вы можете. Проверка того, что месяц является действительным григорианским месяцем, и овладение григорианскими месяцами - это отдельная задача от создания месяцев в целом.
Каждый из (1) и (2) потенциально является правильным дизайном.
Если в класс Month
встроена большая логика, предполагающая использование григорианского календаря, маловероятно, что будет использоваться (2), он просто даст неправильные ответы, если вы попытаетесь использовать класс в Еврейский календарь. Поскольку григорианский календарь никогда не изменится (мы все искренне надеемся), не так много времени нужно для того, чтобы сделать класс тестируемым в случаях, которые не являются действительными григорианскими месяцами. Я, честно говоря, не могу предсказать, как изменится календарь, если он действительно изменится, поэтому я не могу писать тесты, чтобы убедиться, что мой код готов к изменениям. Так что (1) это, вероятно, все, что вы когда-либо захотите.
Если Month
ничего не делает сам по себе, это просто что-то, что соединяется вместе, чтобы составить год, а интеллектуальный календарь лежит в другом месте, тогда (2) может быть полезно - вы или кто-то еще - использовать его для реализации других календарей. В принципе я выступаю за предоставление пользователям моих классов как можно большей гибкости, хотя на практике иногда это приводит к бремени модульного тестирования в классе, что неоправданно.