这是一个糟糕的oop设计吗?

Xai*_*oft 21 .net c# oop design-patterns class-design

我有一个名为Chicken的类,在Chicken中我有一些方法,所以在另一个我实例化并调用Chicken方法的类中,我可能会这样做:

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


public void UpdateChicken(Chicken chicken)
{ 
   chicken.Update(chicken);
}
Run Code Online (Sandbox Code Playgroud)

以上是罚款还是存在问题,如果是这样,最好还有另一个类,例如ChickenCalculations,并执行以下操作:

public void UpdateChick(Chicken chicken)
{
    ChickenCalculations.Update(chicken);
}
Run Code Online (Sandbox Code Playgroud)

这是一个实现:

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

Chicken anotherChicken = new Chicken()
anotherChicken.Update(chicken);
chicken.Update(chicken)
Run Code Online (Sandbox Code Playgroud)

这是一个更实际的例子,而不是使用鸡:

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);
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

Cod*_*ray 27

为什么UpdateChicken函数不是Chicken该类的成员?

这样,您就不必传入Chicken对象的实例,而只需Update在现有实例上调用该方法:

Chicken chicken = new Chicken("Name", "Description");
chicken.Update();
Run Code Online (Sandbox Code Playgroud)

通常最好封装对该类内部特定类进行操作的所有方法,而不是将它们拆分为单独的"辅助"类.让他们自己管理!

  • @Cody,将所有行为放在一个类中最终会导致非常大的类具有相互独立的相关行为块.解决这个问题是访客模式的原因之一.另一个例子是WCF类; 通常使数据类完全轻量级并且将数据类上的操作*保持在单独的(在服务中).这允许您在其自己的类中(并且可能在其自己的*程序集*中)对相关行为进行分组. (9认同)
  • "为什么UpdateChicken函数不是Chicken类的成员":可能,猪想要更新鸡?:) (5认同)
  • @Kirk:是的,我说这样做"通常"最好.在设计模式方面,我不相信"规则"或任何绝对的东西.我还指出,与'Chicken`对象直接相关*的所有内容都应该在`Chicken`类中.我仍然认为这是真的.将这些功能分解为辅助类很少是个好主意.我更喜欢保持我的模型简单直观,而不是试图围绕当天的最新模式/模型. (5认同)
  • 说那个男人.阅读`chicken.Update(鸡);`给了我眩晕. (3认同)
  • @khachik:嗯,当然.但是你会把猪的一个实例传给'鸡'类,他可以自己调用`Update`方法! (2认同)

Yoc*_*mer 9

面向对象编程的整个想法是将对象视为能够对自己采取行动.

所以你应该只是chicken.Update()用来更新一只鸡.


Jus*_*tin 8

我将以你的AirlineBooking课程为例,因为很多人似乎对这个Chicken例子感到困惑.

一些介绍:

单一职责原则规定,一个对象应该有一个单一的责任,它应该只关心自己的事情narow与责任一致.例如,a TaxCalculator应该负责计算税,而不是,例如,转换货币 - 这是工作的CurrencyConverter.

这通常是一个非常好的主意,因为它意味着您的应用程序被组织成代码块,每个代码都有一个单一的责任,使其更容易理解,更安全.另一种方法是,一个类或模块应该只有一个改变的理由,例如"我们计算税收的方式已经改变",或"我们转换货币的方式已经改变".


您需要问自己的问题是:

  • 有什么责任AirlineBooking
  • 更新航空公司预订部分责任吗?

例如,在这种情况下,我会说责任AirlineBooking是"封装航空公司预订",更新航空公司预订实际上是预订系统的责任,而不是AirlineBooking.

另外,另一种思考方式是,如果我把Update方法放在AirlineBooking这上意味着:

  • 如果预订系统更改为使用Web服务而不是存储过程,则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.
    }
}
Run Code Online (Sandbox Code Playgroud)

您应该问自己这些问题的原因是因为它取决于AirlineBooking您的应用程序中使用的内容.

例如,如果AirlineBooking是"知道"(即有参考)预订系统,那么你可以添加一个"帮助"方法,如下所示:

public class AirlineBooking
{
    public void Update(int id)
    {
        this.bookingSystem.UpdateBooking(this, id);
    }
}
Run Code Online (Sandbox Code Playgroud)