gpt4 book ai didi

java - 工厂方法/抽象工厂模式的使用

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:22:06 25 4
gpt4 key购买 nike

我有以下简化的解析库存文件的要求,该文件包含汽车品牌字母和每行相应的规范字符串。例如:

A Sedan
B Blue

下面我提供了一个简化版的代码:

    class StockManager
{
List<ICar> cars = new List<ICar>();
public StockManager(List<string> inventoryFileLines)
{
foreach(var inventoryFileLine in inventoryFileLines)
{
string[] parts = inventoryFileLine.Split(' ');
cars.Add(CreateCar(parts[0], parts[1]));
}
}

public decimal CalculateTotal()
{
decimal total = 0;
foreach(var car in cars)
{
total += car.GetPrice();
}
return total;
}

public ICar CreateCar(string brand, string spec)
{
if(brand == "A")
{
return new CarA(spec);
}else if(brand == "B")
{
return new CarB(spec);
}
throw new Exception();
}
}


interface ICar
{
decimal GetPrice();
}

class CarA : ICar
{
string type;

public CarA(string type)
{
this.type = type;
}
public decimal GetPrice()
{
if(type == "Sedan")
{
return 30000;
}
else if (type == "SUV")
{
return 50000;
}
throw new Exception();
}
}

class CarB : ICar
{
string color;

public CarB(string color)
{
this.color = color;
}
public decimal GetPrice()
{
if (color == "Orange")
{
return 20000;
}else if (color == "Red")
{
return 25000;
}
throw new Exception();
}
}

将来可能会添加新的品牌和规范。这是我应该预见并提供灵 active 的变化。现在我想应用正确的设计模式,但要出于正确的原因应用它们,而不仅仅是为了应用设计模式。 (正如 GoF 所说:“只有在实际需要其提供的灵 active 时才应应用设计模式。”)

我首先想到的是工厂方法或抽象工厂模式。所以当以后有新的汽车品牌C加入时:

工厂方法

将 CreateCar 设为虚拟并在我将使用的新 StockManager 类中覆盖它:

class StockManager2 : StockManager
{
public StockManager2(List<string> inventoryFileLines) : base(inventoryFileLines) { }
public override ICar CreateCar(string brand, string spec)
{
if (brand == "C")
{
...
}
return base.CreateCar(brand, spec);
}
}

抽象工厂

将CreateCar方法做成自己的抽象工厂类,提供给StockManager类。


如果我想在运行时使用不同的替代创建选项,例如多个有效的 CreateCar 工厂,这两种重构看起来都很棒。而GoF给出的Maze例子也扩展了这个思路。

但事实上,我预期的变化不是替代工厂,而是改造工厂。所以对我来说,修改 CreateCar 方法而不是创建一个新的工厂类并让旧的工厂类过时(这里指的是抽象工厂方法)似乎更合乎逻辑。在工厂方法的情况下,创建第二个 StockManager2 类也是如此。我知道开放/封闭原则(Robert Martin 的 SOLID 的 O)说不要修改类而是扩展它,而工厂模式正是这样做的但是上面的例子是否证明了它的使用,考虑到我在开头提到的可扩展性要求?似乎要求不是 GoF 中解释的意义上的扩展,而是真正的修改。但如果我错了,我希望得到纠正。

最佳答案

您可以使用运行时对象创建机制。因此,c# 将根据字符串创建类。唯一期望类名和给定的字符串必须相同。

但如果值不相同,您可以使用静态字典。这是代码:

public ICar CreateCar(string brand, string spec)
{
System.Type type = typeof( ICar ).Assembly.GetTypes().Where( t => t.Name == brand ).FirstOrDefault();

object instance = Activator.CreateInstance( type, new object[ 1 ] { specs } );
return (ICar)instance;
}

当然这个函数不处理任何错误,但它是容易的部分。顺便说一下,在您的代码中请使用 NotImplementedException 而不是 Exception 基类,因为这是您想要的:) 实现新品牌。

关于java - 工厂方法/抽象工厂模式的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53269400/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com