| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Общие вопросы по .NET и C# > спроектировать класс |
| Автор: 17dufa 11.3.2010, 14:31 |
| задача простая до безобразия, а я туплю: есть заказ, есть позиции в заказе. задача - написать структуру классов таким образом, чтобы позицию нельзя было создать вне заказа. мои варианты: 1. запихнуть это в сборку, конструктор позиции internal, у заказа есть public метод AddPosition, который уже создаст позицию. Но есть одна жопа: если класс позиции бум часто менять постоянно придется менять 3 части: сам класс позиции, метод AddPosition, клиента, который вызывает AddPosition. 1 и 3 части неизбежны, а вот изменения в самом методе AddPosition вроде как бы неплохо выкинуть. но как? создать еще один класс (точнее наверно структуру) с названием Данные_Позиции. клиент ее заполняет, передает в AddPosition, а тот передает в конструктор позиции? тогда изменения будут касаться только этой структуры и метод AddPosition менять не придется. 2. в конструкторе позиции передавать заказ, в который она входит. дальше встает вопрос - а как заказ узнает о своей позиции? делать в заказе метод типа RegisterPosition и обязывать конструктор позиции его вызывать? во-первых кривовато, во-вторых встает задача как спрятать сам метод RegisterPosition, чтоб его не вызывали кто не попадя. 3. можно подумать что-то насчет вложенных классов, но чего именно подумать не придумывается. |
| Автор: uranpro 11.3.2010, 16:45 | ||
не совсем понял, но... =)
|
| Автор: 17dufa 11.3.2010, 17:13 |
| uranpro, теперь представим, что Pos у нас крайне неустойчивый класс, то добавится поле, то тип поменяет. придется менять: 1. сам класс Pos 2. метод Zakaz::AddPos 3. клиентский код, который юзает Zakaz::AddPos можно пункт 2 исключить? |
| Автор: uranpro 11.3.2010, 17:24 | ||||
| 17dufa, я показал как использовать приватные конструкторы и как пользоваться модификатором доступа "protected internal". вопрос был такой, насколько я понял: как сделать так, чтобы экземпляры позиций можно было создать только в экземпляре заказа =) мб так
Добавлено через 2 минуты и 36 секунд
|
| Автор: 17dufa 11.3.2010, 17:55 | ||||
| uranpro, да, этот вариант решает поставленную задачу. так же как и вариант с internal в отдельной сборке и как вариант с передачей экземпляра класса заказа в конструктор позиции. но этот вариант имеет некоторый недостаток, на который мне было указано, когда я утром отвечал на данный вопрос на собеседовании, а именно: что будет, если класс заказа будет меняться? будет собственно говоря не очень хорошая штука: придется слишком много кода править. можно это обойти? кстати, придумал как можно:
правда решая проблему изменчивости класса заказа, такое решение порождает более серьезную проблему: во-первых, объект позиции выходит из конструктора в несколько противоречивом состоянии, во-вторых, нет способа заставить клиента вызвать метод Init, то есть вполне возможна ситуация:
|
| Автор: uranpro 11.3.2010, 18:37 |
| 17dufa, не пойму в чем проблема, меняется класс заказа, а не позиции =( а если использовать перегрузку ? |
| Автор: 17dufa 11.3.2010, 19:23 | ||||||
uranpro, вот смотри допустим у нас в позиции хранится тока стоимость, будет что-то типа:
потом мы подумали и решили, что не плохо б еще сохранить ссылку на товар, получается:
потом бац, нафиг цену, в товаре есть цена за единицу, бум хранить количество:
и тд и каждый раз эти изменения затрагивают 3! места: 1. конструктор класса Pos 2. метод Zakaz::NewPos 3. клиентский код, который этот NewPos вызывает. 1 и 3 место как бы неизбежны, а вот менять постоянно Zakaz::NewPos быстро надоест, учитывая что изменения сугубо механические - изменить аргументы, передать эти аргументы в конструктор класса Pos. |
| Автор: uranpro 12.3.2010, 11:25 | ||||
а если сделать так
--- лучше даже так =)
|
| Автор: 17dufa 12.3.2010, 16:03 | ||
| uranpro, кстати, интересный вариант но и у него есть минус - выключается компайл-тайм проверка типов. вообщем никак не пойму, к какому же решению меня подталкивали на собеседовании. ща прям у них и спрошу. как вариант делать кроме класса Pos еще некоторую структуру PosInitializationData и соответственно:
и меняй эту структуру скока хошь. |
| Автор: uranpro 12.3.2010, 16:09 |
| =) спроси, тож интересно стало)) да, можно и так |
| Автор: 17dufa 12.3.2010, 20:32 | ||
немного неожиданно, но ответили:
Добавлено @ 20:34 то есть практически второй предложенный мной вариант, когда позиции сами добавляют себя в заказ, хех немного не дожал вопросик. все-таки меня немного смущает данная реализация, как заставить класс позиции в конструкторе обязательно вызывать метод AddItem у переданного ему экземпляра класса заказа? не очень хорошее место. размытие ответственности некое, в случае чего виноватых не найдешь |
| Автор: mihryak 13.3.2010, 01:56 |
| вообще, решение "DTO" (3ий вариант) довольно широко применяется т.е. общение клиент-сервис идёт посредством контейнеров с данными вместо сущностных классов в исходном виде |
| Автор: uranpro 13.3.2010, 11:08 |
| =) |
| Автор: 17dufa 15.3.2010, 14:13 |
| mihryak, я со счета сбился, третий - это с созданием структуры PosInitializationData? |
| Автор: mihryak 17.3.2010, 21:51 | ||
это я сбился
про этот вариант написал |