Подтвердить что ты не робот

Это плохой дизайн?

У меня есть класс под названием Chicken and in Chicken У меня есть несколько методов, поэтому в другом классе, где я создаю экземпляр и вызываю методы на Chicken, я мог бы сделать что-то вроде этого:

Chicken chicken = new Chicken("Name","Description")


public void UpdateChicken(Chicken chicken)
{ 
   chicken.Update(chicken);
}

Является ли это прекрасным или создает проблемы, если это так, лучше иметь другой класс, например ChickenCalculations, и делать что-то вроде:

public void UpdateChick(Chicken chicken)
{
    ChickenCalculations.Update(chicken);
}

Вот реализация:

Chicken chicken = new Chicken("Bob","Coolest Chicken", 4, 123, 5, 388, true, false, true);

Chicken anotherChicken = new Chicken()
anotherChicken.Update(chicken);
chicken.Update(chicken)

Вот более практичный пример вместо использования цыпленка:

public class AirlineBooking
{
    int BookingId {get;set;}
    string Name {get;set;}
    string Description {get;set;}
    decimal Price {get;set;}
    decimal Tax {get;set;}
    string seat {get;set;}
    bool IsActive {get;set;}
    bool IsCanceld {get;set;}


    public AirlineBooking(string name, string description, decimal price, 
                          decimal tax, string seat, bool isActive, bool isCanceled)
    {
        Name = name;
        Description = description;
        Price = price;
        Tax = tax;
        Seat = seat;
        IsActive = isActive;
        IsCanceled = isCanceled;
    }

    public Update(AirlineBooking airlineBooking, int id)
    {
          //Call stored proc here to update booking by id
    }

    public class BookingSystem
    {
       //Create new booking
       AirlineBooking booking = new AirlineBooking("ticket-1",
                                                   "desc",150.2,22.0,
                                                   "22A",true, false);

       //Change properties and update.
       booking.Name ="ticket-2";
       booking.Description = "desc2";
       booking.Price = 200.52;
       booking.Tax = 38.50;

       public void UpdateBooking(AirlineBooking booking, int id)
       {
            /* This is the meat of the question, should the passed in booking to
               update itself or should I have a Service Class , such as
               AirlineBookingOperations with an update method. */
            booking.Update(booking,id);
       }
    }
}
4b9b3361

Ответ 1

Почему функция UpdateChicken не является членом класса Chicken?

Таким образом, вам не нужно будет передавать экземпляр объекта Chicken, а просто вызвать метод Update в существующем экземпляре:

Chicken chicken = new Chicken("Name", "Description");
chicken.Update();

Как правило, лучше всего инкапсулировать все методы, которые работают с определенным классом внутри этого класса, а не разделять их на отдельный класс "помощник". Пусть их куры управляют собой!

Ответ 2

Вся идея объектно-ориентированного программирования - думать о объектах, способных действовать на себя.

Итак, вы должны просто использовать chicken.Update() для обновления цыпленка.

Ответ 3

Я собираюсь использовать ваш класс AirlineBooking в качестве примера, потому что многие люди, похоже, запутались в примере Chicken.

Некоторое введение:

принцип единой ответственности утверждает, что объект должен иметь одиночную ответственность и что он должен касаться только вещи противоречат этой ответственности. Например, TaxCalculator должен только нести ответственность за расчет налога, а не, например, при конвертировании валюты - это задание CurrencyConverter.

Это часто очень хорошая идея, так как это означает, что ваше приложение структурировано в куски кода, каждый из которых несет единую ответственность, что упрощает понимание и безопасность для изменения. Другой способ поставить это в том, что класс или модуль должны иметь одну и только одну причину изменения, например "То, как мы вычисляем налог, изменилось", или "Способ преобразования валюты изменился".


Вопросы, которые вам нужно задать сами:

  • Ответственность за AirlineBooking?
  • Является ли обновление части бронирования авиакомпании частью этой ответственности?

Например, в этом случае я бы сказал, что ответственность AirlineBooking - "Инкапсуляция бронирования авиабилетов", и что обновление бронирования авиакомпании фактически является ответственностью системы бронирования, а не AirlineBooking.

Альтернвно, другой способ думать об этом заключается в том, что если я положу метод Update на AirlineBooking, это будет означать, что:

  • Если система бронирования изменит использование веб-службы, а не хранимой процедуры, то класс AirlineBooking должен измениться.
  • Если инкапсуляция изменений в бронировании авиакомпании (возможно, возможно приостановить бронирование, или название авиакомпании теперь записано), то AirlineBooking необходимо изменить.

т.е. AirlineBooking теперь имеет много разных причин для изменения, и поэтому он также не должен отвечать за "Обновление"


Короче говоря, я бы это сделал:

public class AirlineBooking
{
    public int BookingId {get;set;}
    /* Other properties */
}

public class BookingSystem
{
    public void UpdateBooking(AirlineBooking booking, int id)
    {
        // Call your SP here.
    }
}

Причина, по которой вы должны задать себе эти вопросы, заключается в том, что она зависит от того, для чего AirlineBooking используется в вашем приложении.

Например, если AirlineBooking "осведомлен" (т.е. имеет ссылку) в системе бронирования, вы можете добавить "вспомогательный" метод, например:

public class AirlineBooking
{
    public void Update(int id)
    {
        this.bookingSystem.UpdateBooking(this, id);
    }
}

Ответ 4

Почему бы вам не дать вашему классу Chicken метод "Обновить (некоторые параметры...)"? Затем вы можете просто создать курицу с помощью

Chicken chicken = new Chicken("Name", "descr");

и обновить:

chicken.Update(myparameters..);

ИЗМЕНИТЬ

public class Chicken
{
  public Chicken(string name, string description)
  {
     this.Name = name;
     this.Description = description;
  }

  public string Name { get; set; }
  public string Description { get; set; }

  // Fill in all the other properties!

  public int EggsDroppedInLife { get; set; }
}

И теперь вы можете использовать свой класс курицы следующим образом:

Chicken chicken = new Chicken("Harry", "Nice chick");
chicken.NumberOfEggs = 123;
chicken.Description = "Oh no, it actually not nice.";
// ... change all the properties as you want

Ответ 5

Объекты должны инкапсулировать функциональность. Функциональность должна быть передана, чтобы обеспечить гибкость инкапсулирующего объекта.

Итак, если вы сохраняете цыпленка, вы должны перейти в функции репозитория. Если у вас есть расчеты цыплят, и они подвержены изменениям, они также должны быть переданы.

class Chicken
{
   IChickenCalculations ChickenCalculations;
   IChickenRepository ChickenRepository;
   Chicken(IChickenCalculations chickenCalculations, IChickenRepository chickenRepository)
   {
       ChickenCalculations = chickenCalculations;
       ChickenRepository = chickenRepository ;
   }

   Calculate()
   {
       ChickenCalculations.Calculate(this);
   }
   Update()
   {
       ChickenRepository.Update(this);
   }
}

Обратите внимание, что как в этом примере цыпленок способен выполнять вычисления сам по себе и упорствовать, не имея никакого знания о том, как выполнять вычисления или сохраняющиеся вещи (в конце концов, это только цыпленок).

Ответ 6

Пока я понимаю, что нет Chicken, на вашем реальном объекте может быть метод Update, правильно?

Я думаю, вы должны попробовать представить что-то еще, чем "обновление" в терминах языка. Невозможно понять, что делает обновление. Он просто обновляет "данные" в "Цыпленке"? В таком случае какие данные? А также, если вам разрешено обновлять экземпляр Курицы?

Я бы предпочел посмотреть что-то вроде

chicken.CanFly = false;
if(chicken.CanFly)  // inherited from Bird :)
    ckicken.FlyTo(point);
else
    chicken.WalkTo(point);

Вот довольно интересное упражнение в ООП: http://milano-xpug.pbworks.com/f/10080616-extreme-oop.pdf

Ответ 7

Для многопоточной среды лучше всего подходит отдельный класс, такой как ChickenCalculations. Когда вам нужно выполнить несколько других шагов, кроме того, что делает chicken.Update(), вы можете сделать это с помощью класса ChickenCalculations. Поэтому, если несколько классов, которые создают экземпляр и вызывают методы на Chicken, не нужно беспокоиться о тех вещах, о которых заботится класс ChickenCalculations.