Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> спроектировать класс 
:(
    Опции темы
17dufa
Дата 11.3.2010, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



задача простая до безобразия, а я туплю:
есть заказ, есть позиции в заказе. задача - написать структуру классов таким образом, чтобы позицию нельзя было создать вне заказа.
мои варианты:
1. запихнуть это в сборку, конструктор позиции internal, у заказа есть public метод AddPosition, который уже создаст позицию. Но есть одна жопа: если класс позиции бум часто менять постоянно придется менять 3 части: сам класс позиции, метод AddPosition, клиента, который вызывает AddPosition. 1 и 3 части неизбежны, а вот изменения в самом методе AddPosition вроде как бы неплохо выкинуть. но как? создать еще один класс (точнее наверно структуру) с названием Данные_Позиции. клиент ее заполняет, передает в AddPosition, а тот передает в конструктор позиции? тогда изменения будут касаться только этой структуры и метод AddPosition менять не придется.
2. в конструкторе позиции передавать заказ, в который она входит. дальше встает вопрос - а как заказ узнает о своей позиции? делать в заказе метод типа RegisterPosition и обязывать конструктор позиции его вызывать? во-первых кривовато, во-вторых встает задача как спрятать сам метод RegisterPosition, чтоб его не вызывали кто не попадя.
3. можно подумать что-то насчет вложенных классов, но чего именно подумать не придумывается.

Это сообщение отредактировал(а) 17dufa - 11.3.2010, 16:05
PM MAIL   Вверх
uranpro
Дата 11.3.2010, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: 1
Всего: 1



не совсем понял, но... =)
Код

    public class Zakaz
    {
        public class Pos
        {
            public int ID { get; set; }
            private Pos(int ID)
            {
                this.ID = ID;
            }

            static protected internal Pos GetNewInstance(int ID)
            {
                return new Pos(ID);
            }
        }

        public List<Pos> Positions = new List<Pos>();

        public void AddPos(int ID)
        {
            Positions.Add(Pos.GetNewInstance(ID));
        }

    }



--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
17dufa
Дата 11.3.2010, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



uranpro, теперь представим, что Pos у нас крайне неустойчивый класс, то добавится поле, то тип поменяет. придется менять:
1. сам класс Pos
2. метод Zakaz::AddPos
3. клиентский код, который юзает Zakaz::AddPos
можно пункт 2 исключить?
PM MAIL   Вверх
uranpro
  Дата 11.3.2010, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: 1
Всего: 1



17dufa, я показал как использовать приватные конструкторы и как пользоваться модификатором доступа "protected internal".
вопрос был такой, насколько я понял: как сделать так, чтобы экземпляры позиций можно было создать только в экземпляре заказа =)
мб так
Код

    public class Zakaz
    {
        public class Pos
        {
            public int ID { get; set; }
            private Pos() { }
            static protected internal Pos GetNewInstance()
            {
                return new Pos();
            }
        }

        public List<Pos> Positions = new List<Pos>();

        public Pos NewPos()
        {
            return Pos.GetNewInstance();
        }
    }


Добавлено через 2 минуты и 36 секунд
Код

var z = new Zakaz();
            Zakaz.Pos p = z.NewPos();
...
Zakaz.Pos p = new Zakaz.Pos();// ошибка



--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
17dufa
Дата 11.3.2010, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



uranpro, да, этот вариант решает поставленную задачу. так же как и вариант с internal в отдельной сборке и как вариант с передачей экземпляра класса заказа в конструктор позиции. но этот вариант имеет некоторый недостаток, на который мне было указано, когда я утром отвечал на данный вопрос на собеседовании, а именно:
что будет, если класс заказа будет меняться? будет собственно говоря не очень хорошая штука: придется слишком много кода править. можно это обойти?
кстати, придумал как можно:
Код

Zakaz z = new Zakaz();
z.NewPos().Init(/*необходимые параметры, меняй скока хошь*/);

правда решая проблему изменчивости класса заказа, такое решение порождает более серьезную проблему: во-первых, объект позиции выходит из конструктора в несколько противоречивом состоянии, во-вторых, нет способа заставить клиента вызвать метод Init, то есть вполне возможна ситуация:
Код

Zakaz z = new Zakaz();
z.NewPos(); /*а Init никто и не вызвал*/

PM MAIL   Вверх
uranpro
Дата 11.3.2010, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: 1
Всего: 1



17dufa, не пойму в чем проблема, меняется класс заказа, а не позиции =( а если использовать перегрузку ?



--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
17dufa
Дата 11.3.2010, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



uranpro, вот смотри допустим у нас в позиции хранится тока стоимость, будет что-то типа:
Код

double cost = ....
Zakaz.Pos p = z.NewPos(cost);

потом мы подумали и решили, что не плохо б еще сохранить ссылку на товар, получается:
Код

double cost = ....
Tovar t = ....
Zakaz.Pos p = z.NewPos(cost, t);

потом бац, нафиг цену, в товаре есть цена за единицу, бум хранить количество:
Код

int kolvo = ....
Tovar t = ....
Zakaz.Pos p = z.NewPos(kolvo, t);

и тд
и каждый раз эти изменения затрагивают 3! места:
1. конструктор класса Pos
2. метод Zakaz::NewPos
3. клиентский код, который этот NewPos вызывает.
1 и 3 место как бы неизбежны, а вот менять постоянно Zakaz::NewPos быстро надоест, учитывая что изменения сугубо механические - изменить аргументы, передать эти аргументы в конструктор класса Pos.
PM MAIL   Вверх
uranpro
Дата 12.3.2010, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: 1
Всего: 1



а если сделать так
Код

static protected internal Pos GetNewInstance(object[] args)
public Pos NewPos(object[] args)


---
лучше даже так =)
Код

static protected internal Pos GetNewInstance(params object[] args)
public Pos NewPos(params object[] args)


Это сообщение отредактировал(а) uranpro - 12.3.2010, 12:37


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
17dufa
Дата 12.3.2010, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



uranpro, кстати, интересный вариант smile 
но и у него есть минус - выключается компайл-тайм проверка типов.
вообщем никак не пойму, к какому же решению меня подталкивали на собеседовании. ща прям у них и спрошу.
как вариант делать кроме класса Pos еще некоторую структуру PosInitializationData и соответственно:
Код

static protected internal Pos GetNewInstance(PosInitializationData data)
public Pos NewPos(PosInitializationData data)

и меняй эту структуру скока хошь.
PM MAIL   Вверх
uranpro
Дата 12.3.2010, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: 1
Всего: 1



=) спроси, тож интересно стало)) да, можно и так


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
17dufa
Дата 12.3.2010, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



немного неожиданно, но ответили:
Код

public class Order

    {

        private IList<Item> _itemList;

        public long Id { get; protected set; }

        public string Customer {get;set;} //не выделяем в отдельную сущность (по условию задачи)

        public string Date {get; set;}

        public double Sum { get { /* реализация*/return 0; } }

 

        public Order()

        {

            _itemList = new List<Item>();

        }

 

        public virtual ReadOnlyCollection<Item> Items

        {

            get

            {

                return new ReadOnlyCollection<Item>(_itemList);

            }

        }

 

        protected internal void AddItem(Item item)

        {

            if (item != null) //в упрощенном варианте

                _itemList.Add(item);

        }

    }

 

    public class Item

    {

        public long Id { get; protected set; }

        public string Material { get; set; } //не выделяем в отдельную сущность (по условию задачи)

        public double Count { get; set; }

        public double Price { get; set; }

        public double Sum { get { /* реализация*/return 0; } }

        public Order Order{get; protected set;}

 

        public Item(Order order)

        {

            Order = order;

            order.AddItem(this);

        }

    }


Добавлено @ 20:34
то есть практически второй предложенный мной вариант, когда позиции сами добавляют себя в заказ, хех немного не дожал вопросик.

все-таки меня немного смущает данная реализация, как заставить класс позиции в конструкторе обязательно вызывать метод AddItem у переданного ему экземпляра класса заказа? не очень хорошее место. размытие ответственности некое, в случае чего виноватых не найдешь smile 

Это сообщение отредактировал(а) 17dufa - 12.3.2010, 21:07
PM MAIL   Вверх
mihryak
Дата 13.3.2010, 01:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 731
Регистрация: 28.4.2007
Где: С-Пб

Репутация: 19
Всего: 36



вообще, решение "DTO" (3ий вариант) довольно широко применяется
т.е. общение клиент-сервис идёт посредством контейнеров с данными вместо сущностных классов в исходном виде
PM MAIL ICQ   Вверх
uranpro
Дата 13.3.2010, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: 1
Всего: 1



=)


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
17dufa
Дата 15.3.2010, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



mihryak, я со счета сбился, третий - это с созданием структуры PosInitializationData?
PM MAIL   Вверх
mihryak
Дата 17.3.2010, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 731
Регистрация: 28.4.2007
Где: С-Пб

Репутация: 19
Всего: 36



это я сбился smile
Цитата(17dufa @  11.3.2010,  15:31 Найти цитируемый пост)
создать еще один класс (точнее наверно структуру) с названием Данные_Позиции

про этот вариант написал

PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0543 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.