简体   繁体   English

设计 class 以容纳其他类的多个实例

[英]Design class to hold multiple instances of other classes

How do you design a class that can hold instances of other classes.你如何设计一个可以容纳其他类的实例的 class。 I'll try to explain.我会尽力解释。 A Customer class instance for every new customer.每个新客户的Customer class 实例。 A customer buys cars and then does specific operations to each car.客户购买汽车,然后对每辆汽车进行特定操作。 For example,例如,

Customer c = new Customer();
// customer buys cars 
c.buyMercedes();
c.buyBMW();
// operations done on the car
c.changeMercedesColor();
c.changeBMWtyres();

Can I do something like this:我可以做这样的事情:

Customer c = new Customer();
c.buy(Mercedes);
c.buy(BMW);
c.car("Mercedes").changeColor();
c.car("BMW").changetyres();

There are no operations specific to any car.没有特定于任何汽车的操作。 I'm thinking that maybe there is a way where a Car class is instantiated when buy() method is called.我在想也许有一种方法可以在调用buy()方法时实例化Car class 。 What is the proper way to design a class for this?为此设计 class 的正确方法是什么? If there is a different way I should go about this, please let me know.如果有不同的方式我应该 go 关于这个,请告诉我。

The easiest way is to create a base class for the different types of cars.最简单的方法是为不同类型的汽车创建一个基础 class。 All your specific cars (Mercedes, BMW) will derive from this.您所有的特定汽车(梅赛德斯、宝马)都将由此衍生。 By using a common base class or interface, your Customer class can operate on the specific cars without having any understanding of them specifically.通过使用通用基础 class 或接口,您的客户 class 可以对特定汽车进行操作,而无需具体了解它们。

public abstract class CarBase
{
    private string _color;

    public virtual void ChangeTires()
    {
         // do the default change tires
    }

    public virtual void ChangeColor(string _color)
    {
         _color = color;
    }
}

You can then create specific types of cars:然后,您可以创建特定类型的汽车:

public class Mercedes : CarBase
{
    public override void ChangeColor(string color)
    {

    }

}

Because each method in CarBase is virtual, each specific implementation can offer up it's own implementation if it needs, otherwise it just relies on the 'default' ChangeTires().因为 CarBase 中的每个方法都是虚拟的,所以如果需要,每个特定的实现都可以提供自己的实现,否则它只依赖“默认”ChangeTires()。

For instance, perhaps with Mercedes, changing the color means you must get special tires.例如,也许对于梅赛德斯来说,改变颜色意味着你必须得到特殊的轮胎。

public class Mercedes : CarBase
{
    public override void ChangeColor(string color)
    {
         if (color == red)
             AddRacingTires();
    }
} 

You can then supply a method for Customer that adds a new vehicle.然后,您可以为客户提供添加新车辆的方法。

public class Customer
{
    public Dictionary<string, CarBase> OwnedCars { get; set; }

    public void BuyCar(string manufacture)
    {
        if (manufacture== "Mercedes")
           OwnedCars[manufactor] = new Mercedes();

        if (manufacture== "BMW")
           OwnedCars[manufactor] = new BMW();
    }
}

You can then do things like:然后,您可以执行以下操作:

Customer c = new Customer();

c.BuyCar("Mercedes");

c.OwnedCars["Mercedes"].ChangeTires();

There's better ways to manage the cars.有更好的方法来管理汽车。 You probably want to look at a factory for creating cars: http://www.dofactory.com/Patterns/PatternFactory.aspx您可能想看看制造汽车的工厂: http://www.dofactory.com/Patterns/PatternFactory.aspx

You probably also don't want a Dictionary of manufactures (i'd imagine you'd reference them by VIN or something).您可能也不想要制造商词典(我想您会通过 VIN 或其他东西来引用它们)。 You also don't want magic strings like "Mercedes", since you might mis-type it somewhere.您也不想要像“Mercedes”这样的魔术字符串,因为您可能会在某处输入错误。 But this is the basic design pattern that might work best.但这是可能效果最好的基本设计模式。

You want composition.你想要作曲。 You can have an generic list of Car s and access them from there.您可以拥有Car的通用列表并从那里访问它们。

If there are no operations specific to any particular car, then you would just have "Make" and/or "Model" be properties of the cars.如果没有特定于任何特定汽车的操作,那么您只需将“制造”和/或“型号”作为汽车的属性。

The second form is without a doubt superior to the first form.第二种形式无疑优于第一种形式。

Since cars can exist independent of their owners, you should be able to instantiate a car without a customer.由于汽车可以独立于其所有者而存在,因此您应该能够在没有客户的情况下实例化汽车。 Perhaps you can then add operations to Customer to add a new car, and get existing cars.也许您可以向客户添加操作以添加新车并获取现有汽车。 You may also wish to get a car by VIN rather than make.您可能还希望通过 VIN 而不是制造来获得汽车。 Any one customer may own more than one BMW.任何一位客户都可能拥有不止一辆宝马。

The changeColor and changeTyres methods should exist on your Car object instead of your customer object. changeColor 和 changeTyres 方法应该存在于您的 Car object 而不是您的客户 object 上。

Car bmw = carFactory.create("BMW");
customer.add(bmw);
Car bmwAgain = customer.get(bmw.Vin);
bmwAgain.changeColor("black");

Since you don't have operations specific to any car, you don't need to derive from Car.由于您没有特定于任何汽车的操作,因此您不需要从 Car 派生。 Let's assume that you have a Car class that has a Brand property, which is an enum.假设您有一个Car class 具有Brand属性,这是一个枚举。 Then you could design your Customer class like this:然后您可以像这样设计您的客户 class:

Customer c = new Customer();
c.buy(Brands.Mercedes);
c.buy(Brands.BMW);

The buy method would create a new instance of Car , set it's Brand property and add it to cars , an instance variable of Customer of type List<Car> . buy方法将创建一个Car的新实例,设置它的Brand属性并将其添加到cars ,这是一个List<Car>类型的Customer的实例变量。

If you are sure that a customer can only have one car of one brand (no customer with two Mercededes? Maybe an SLK for the weekend and an A for finding a parking spot in the city?), then you can define your interface like this:如果您确定客户只能拥有一个品牌的汽车(没有客户拥有两辆梅赛德斯?也许是周末的 SLK 和在城市寻找停车位的 A?),那么您可以像这样定义您的界面:

c.getCar(Brands.Mercedes).changeColor();
c.getCar(Brands.BMW).changeTyres();

Otherwise, I'd expose an enumeration of cars and use LINQ:否则,我会公开汽车枚举并使用 LINQ:

var mercedeses = c.Cars.Where(car => car.Brand == Brands.Mercedes);
foreach (var car in mercedeces) {
   car.changeTyres();
}

Inheritance an factory is what you need. Inheritance 工厂就是您所需要的。

OK, this sounds a little like homework but:好的,这听起来有点像家庭作业,但是:

if you had items to buy which were all cars, so had commonalities, such as "service", "mot", "lights", "tyres", "exhaust","paint" as items you would then be "changing"如果您要购买的所有物品都是汽车,那么诸如“服务”,“汽车”,“灯”,“轮胎”,“排气”,“油漆”之类的共同点也是您将要“改变”的物品

You could have a base class of BaseCar, which then you descend from to get your BWM/Merc etc.你可以有一个 BaseCar 的基础 class,然后你从它下来得到你的 BWM/Merc 等。

The with each customer, you would have a class where you define the items to buy as the base car, but you can send them the "new Mercedes()" and get a new instance of the actual car they bought.对于每个客户,您将拥有一个 class,您可以在其中将要购买的物品定义为基础汽车,但您可以向他们发送“new Mercedes()”并获得他们购买的实际汽车的新实例。

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

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