繁体   English   中英

抽象和适当的类设计

[英]Abstraction and Proper Class Design

我对编程并不陌生,但是对OOP相对较新,所以我有一个设计问题。 实际上,在同一问题中我有两个问题。

为了简单起见,假设我正在设计一个FruitBasket类。 除了FruitBasket类,我还将设计一个Apple类,一个Orange类和一个Pear类。 每当我实例化FruitBasket类型的对象时,它将自动以has-a关系实例化这些其他类。

class Apple { //Apple implementation here }

class Orange { //Orange implementation here }

class Pear { //Pear implementation here }

class FruitBasket
{
     Apple _apple;
     Orange _orange;
     Pear _pear;

     public FruitBasket()
     {
          _apple = new Apple();
          _orange = new Orange();
          _pear = new Pear();
     }
}

class Program
{
     FruitBasket _fruitBasket;

     static void Main()
     {
          _fruitBasket = new FruitBasket();
     }
}

好的,这是我的问题:

  1. 如图所示,在FruitBasket构造函数中实例化各种水果对象是否可以接受,还是这种不好的做法?
  2. 如果每个水果篮都包含全部三个水果,则此方法似乎很好,但是,如果我要实例化仅包含一个Apple和一个Orange水果篮该怎么办? PearOrange ApplePear 等等,最好的方法是什么?

最好创建一个FruitBasket类来声明每个可能放入篮子的水果,并传递一些参数来告诉FruitBasket类实例化哪个水果类?

我真的不知道哪种方法最有效,或者即使我的想法还在讨论之列。

我的建议是不要为FruitBasket创建默认构造FruitBasket 这样,您可以使用Object Initializer语法完全按照您的意思进行操作。 您将需要像下面那样更改FruitBasket类:

public class FruitBasket
{
    public Apple apple { get; set; }
    public Orange orange { get; set; }
    public Pear pear { get; set; }
}

然后,您将能够如下创建FruitBasket:

var fb1 = new FruitBasket { apple = new Apple() };
var fb2 = new FruitBasket { pear = new Pear() };
var fb3 = new FruitBasket { apple = new Apple() orange = new Orange() };

Object Initializer语法非常强大,如果您的类实际上只是一个“属性包”,那么它通常是最简单的方法。

编辑:您可能还想让您的水果继承自Fruit基类。 如果这样做,则可以结合使用对象初始化语法和集合初始化语法。 如果将FruitBasket类更改为以下内容:

public class FruitBasket
{
    public List<Fruit> fruit { get; set; }
}

您可以按以下方式初始化FruitBasket

var fb3 = new FruitBasket{ fruit = new List<Fruit> { new Apple(), new Orange() } };
var fb4 = new FruitBasket{ fruit = new List<Fruit> { new Orange() } };
var fb5 = new FruitBasket{ fruit = new List<Fruit> { new Apple(), new Orange(), new Pear() } };

水果篮必须有该水果,否则有时可能是空的? 你可以重复任何水果吗? 如果是,则应该研究继承和泛型,在泛型中必须有一个基类Fruit,而篮子可能只是一个泛型List

abstract class Fruit
{

}
class Apple : Fruit
{
    //Apple implementation here
}

class Orange : Fruit
{
    //Orange implementation here
}

class Pear : Fruit
{
    //Pear implementation here
}

class Program
{

    static void Main()
    {
        List<Fruit> _fruitBasket = new List<Fruit>();

        _fruitBasket.Add(new Orange());
        _fruitBasket.Add(new Apple());
    }
}

或者,您可以执行以下操作以使篮子尽可能多地丰富:

abstract class Fruit {}
class Apple :Fruit  { //Apple implementation here }

class Orange : Fruit  { //Orange implementation here }

class Pear :Fruit  { //Pear implementation here }

class FruitBasket
{
     public List<Fruit> Contents {get;set;}

     public FruitBasket()
     {
       Contents = new List<Fruit>{new Apple(), new Orange(), new Pear()};
     }
}

这是我将如何处理该问题的方法。 而不是在篮中使用一组预定义的水果,而是使用“水果集合”使它变得灵活。 您将无法将它们传递到构造函数中,而是通过方法添加它们。 为此,每个水果类都继承相同的接口(例如IFruit)

所以你有了

class Apple : IFruit { ... }
class Orange : IFruit { ... }
etc

好处是,您可以根据需要添加任意种类的水果,而不仅限于苹果,橙子和梨。

水果篮可能看起来像这样

public class FruitBasket {
    public FruitBasket() {
        _basket = new List<IFruit>();
    }

    public List<IFruit> Fruits {
        get { return _basket; }
    } 

    public AddFruit(IFruit fruit) {
        _basket.Add(fruit);
    }

    private readonly List<IFruit> _basket 
}

我会设计不同。

class Fruit
{
}

class Apple : Fruit
{ //Apple implementation here }

class Orange : Fruit
{ //Orange implementation here }

class Pear : Fruit
{ //Pear implementation here }

class FruitBasket
{
     Ilist<Fruit> Fruits;

     public FruitBasket()
     {
          Fruits =new List<Fruit>();
     }

     public AddFruit(Fruit)
     {
     // Add Fruit implementation here
     }

      public RemoveFruit(Fruit)
     {
     // Remove Fruit implementation here
     }

}

class Program
{
     FruitBasket _fruitBasket;

     static void Main()
     {
         Fruit orange=new Orange(); 
         _fruitBasket = new FruitBasket();
         _fruitBasket.AddFruit(orange);
     }
}

大概一个FruitBasket可以容纳任何类型的水果,对吗? 这听起来像多态性和依赖反转的情况。

class FruitBasket {
  readonly List<Fruit> _fruits = new List<Fruit>();
  public FruitBasket(params Fruit[] fruits) {
    _fruits.AddRange(fruits);
  }
}
interface Fruit {}
class Apple : Fruit {}
class Orange : Fruit {}

在OOP中,通常会传递依赖项。“预先了解”什么是依赖项是更具过程性的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM