用于保存其他类的多个实例的设计类

时间:2011-05-31 14:23:08

标签: c# oop design-patterns

如何设计一个可以容纳其他类实例的类。我会试着解释一下。 每个新客户的Customer类实例。客户购买汽车,然后对每辆汽车进行特定操作。 例如,

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

我可以这样做:

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

没有特定于任何汽车的操作。我想也许有一种方法可以在调用Car方法时实例化buy()类。为此设计课程的正确方法是什么?如果我有不同的方式,请告诉我。

6 个答案:

答案 0 :(得分:2)

最简单的方法是为不同类型的汽车创建基类。您的所有特定车型(梅赛德斯,宝马)都将源于此。通过使用公共基类或接口,您的Customer类可以在特定的汽车上运行,而无需具体了解它们。

public abstract class CarBase
{
    private string _color;

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

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

然后您可以创建特定类型的汽车:

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

    }

}

因为CarBase中的每个方法都是虚拟的,所以每个特定的实现都可以在需要时提供它自己的实现,否则它只依赖于'默认'ChangeTires()。

例如,也许梅赛德斯,改变颜色意味着你必须得到特殊轮胎。

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

然后,您可以为客户提供添加新车辆的方法。

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();
    }
}

然后您可以执行以下操作:

Customer c = new Customer();

c.BuyCar("Mercedes");

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

有更好的方法来管理汽车。您可能想要查看工厂来创建汽车:http://www.dofactory.com/Patterns/PatternFactory.aspx

你可能也不想要制作词典(我想你会用VIN或其他东西来引用它们)。你也不想要像“Mercedes”这样的魔术字符串,因为你可能会在某处错误输入它。但这是最有效的基本设计模式。

答案 1 :(得分:1)

你想要作曲。您可以拥有Car的通用列表,并从那里访问它们。

如果没有特定于任何特定汽车的操作,那么您只需将“Make”和/或“Model”作为汽车的属性。

答案 2 :(得分:1)

第二种形式毫无疑问优于第一种形式。

由于汽车可以独立于其所有者而存在,因此您应该能够在没有客户的情况下实例化汽车。也许您可以向客户添加操作以添加新车并获得现有车辆。您可能也希望通过VIN而不是制造汽车。任何一个客户都可能拥有多辆宝马。

changeColor和changeTyres方法应该存在于Car对象而不是客户对象上。

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

答案 3 :(得分:1)

由于您没有特定于任何汽车的操作,因此您无需从汽车派生。假设您有一个Car类具有Brand属性,这是一个枚举。然后你可以像这样设计你的Customer类:

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

buy方法会创建Car的新实例,设置它的Brand属性并将其添加到carsCustomer的实例变量输入List<Car>

如果您确定一个客户只能拥有一个品牌的汽车(没有两个Mercededes的客户?周末可能是SLK而在城市找到停车位的A?),那么您可以定义您的这样的界面:

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

否则,我会公开汽车的枚举并使用LINQ:

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

答案 4 :(得分:0)

继承工厂是您所需要的。

答案 5 :(得分:0)

好的,这听起来有点像家庭作业但是:

如果你有购买的物品都是汽车,那么就有共同点,比如“服务”,“mot”,“灯”,“轮胎”,“排气”,“油漆”作为你那时的物品“改变“

你可以拥有一个BaseCar的基类,然后你可以从中获得你的BWM / Merc等。

对于每个客户,您将有一个班级,您可以在其中定义要作为基础车购买的物品,但您可以向他们发送“新梅赛德斯()”并获得他们购买的实际汽车的新实例。 / p>