C# 创建者在工厂模式中的角色
我无法理解为factory类定义抽象类/接口的作用,这是我在web上所有教程中经常看到的。有人能解释一下创作者界面的重要性吗 以代码形式来说,我有: 代码示例1C# 创建者在工厂模式中的角色,c#,design-patterns,factory-pattern,C#,Design Patterns,Factory Pattern,我无法理解为factory类定义抽象类/接口的作用,这是我在web上所有教程中经常看到的。有人能解释一下创作者界面的重要性吗 以代码形式来说,我有: 代码示例1 // Product public abstract class Vehicle { public string VehicleType { get; set; } } // Concrete Product public class Bike : Vehicle { public Bike() {
// Product
public abstract class Vehicle
{
public string VehicleType { get; set; }
}
// Concrete Product
public class Bike : Vehicle
{
public Bike()
{
VehicleType = "Two Wheeler";
}
}
// Concrete Product
public class Car : Vehicle
{
public Car()
{
VehicleType = "Four Wheeler";
}
}
// Concrete Factory
public class VehicleFactory
{
public Vehicle GetVehicle(string VehicleType)
{
if (VehicleType == "Bike")
return new Bike();
else if (VehicleType == "Car")
return new Car();
else
return null;
}
}
// Client class
public class ClientClass
{
public void Main()
{
VehicleFactory VehicleFactoryObj = new VehicleFactory();
Vehicle BikeObj = VehicleFactoryObj.GetVehicle("Bike");
Vehicle CarObj = VehicleFactoryObj.GetVehicle("Car");
}
}
上述代码不包含“VehicleFactory”类的任何抽象类。但它很好用。现在,为“VehicleFactory”添加抽象类的原因是什么?在我看来,添加抽象类对于抽象工厂方法是有意义的。[如果我错了,请纠正我]
更新:增加了我对工厂模式的理解。
GoF的定义:
定义用于创建对象的接口,但由子类决定
要实例化的类。工厂方法允许类延迟
它用于子类的实例化
据我所知,模式背后的核心问题是,您希望创建不同类的实例,而不向使用者公开创建逻辑。如果我这里有什么问题,请告诉我。我在这里也有点困惑,因为我在网上看到的例子。例如,关于Php和C#示例。我可以在C#示例中理解模式的需求,但在PHP示例中不能。无论如何,下面的陈述将帮助你清楚地理解我的问题
例如,我们的图书馆中有两个车辆类别Bike和Car,它们都有车辆型号。自行车型号以“BK”开头,汽车型号以“CR”开头。现在,我们希望根据车辆型号返回任一类的实例,而不向客户机公开逻辑。[注意这是一个更新的场景,我提出这个场景是因为之前的一个场景在决定类的逻辑上很弱,并且在字符串的使用上造成了混乱]
因此,我们可以创建一个vehicle factory类,它公开了一个返回相应vehicle实例的静态方法
如果客户机知道选择逻辑,那么我可能不需要模式本身。所以,这个可能看起来像:
代码示例2
// Product
public abstract class Vehicle
{
public int NumberOfWheels { get; set; }
}
// Concrete Product
public class Bike : Vehicle
{
public Bike()
{
NumberOfWheels = 2;
}
}
// Concrete Product
public class Car : Vehicle
{
public Car()
{
NumberOfWheels = 4;
}
}
// Client class
public class ClientClass
{
public void Main()
{
String ModelNumber = "BK-125";
Vehicle CurrentVehicle;
if (ModelNumber.Contains("BK"))
{
CurrentVehicle = new Bike();
}
else if(ModelNumber.Contains("CR"))
{
CurrentVehicle = new Car();
}
}
}
工厂模式让我们简单地通过创建工厂来隐藏客户机的创作逻辑。因此,客户机现在只需要调用工厂的create方法,他将得到相应的类实例作为回报。现在代码看起来像
代码示例3
// Product
public abstract class Vehicle
{
public int NumberOfWheels { get; set; }
}
// Concrete Product
public class Bike : Vehicle
{
public Bike()
{
NumberOfWheels = 2;
}
}
// Concrete Product
public class Car : Vehicle
{
public Car()
{
NumberOfWheels = 4;
}
}
// Concrete Factory
public class VehicleFactory
{
public Vehicle GetVehicle(string ModelNumber)
{
if (ModelNumber.Contains("BK"))
return new Bike();
else if (ModelNumber.Contains("CR"))
return new Car();
else
return null;
}
}
// Client class
public class ClientClass
{
public void Main()
{
VehicleFactory VehicleFactoryObj = new VehicleFactory();
Vehicle BikeObj = VehicleFactoryObj.GetVehicle("BK-125");
Vehicle CarObj = VehicleFactoryObj.GetVehicle("CR-394");
}
}
现在的问题是抽象工厂类添加抽象工厂类的一个好处(我从讨论中了解到)是,客户端将能够重写“GetVehicle”方法来重写逻辑。对于他可能创建了更多车辆类别的情况,例如“卡车”。但是,即使在这种情况下,如果他想覆盖所有三个方面的工厂方法,即自行车、汽车和卡车,他也不会有完整的逻辑,因为自行车和汽车创建的逻辑是在工厂方法中编写的。尽管他将能够为所有新车型创建新的逻辑。谁能帮我照一下这个吗 我想在这里说的更多一点是,这个问题是关于工厂模式的,我知道抽象工厂模式需要一个抽象工厂,因为在抽象工厂模式中,我们创建的是工厂工厂工厂。但在工厂模式中,我们只有一个对象工厂,那么为什么我们需要一个工厂接口呢
提前感谢!!:-) 是的,它确实有效,但并不理想
VehicleFactory
有一个非常通用的方法,一旦添加更多车辆,使用该方法将非常麻烦,因为您需要一个非常长的方法来检查所有字符串
想象一下你有15辆车。然后,您需要一个非常长的方法来枚举所有选项并生成正确的汽车。这不仅是不必要的慢,而且很容易出错,因为您可能很容易遗漏/删除某些内容,并且很难进行调试。一般来说,长方法是不好的代码气味
除此之外,每次添加继承Vehicle
的内容时,都需要编辑VehicleFactory
类。但是,如果库的用户没有访问权限,但希望从Vehicle继承,会发生什么情况?但是,通过定义一个抽象的VehicleFactory
类,他可以从中继承并定义自己的工厂方法
简而言之,抽象工厂方法使代码更易于扩展
另外,根据字符串生成车辆也是一个非常糟糕的主意;如果您使用大写字母或拼写错误怎么办?除此之外,它的速度相当慢。最好有这样的东西
public abstract class VehicleFactory
{
public abstract Vehicle GetVehicle(string VehicleType)
}
public class CarFactory : VehicleFactory
{
public override Vehicle GetVehicle(string VehicleType)
{
return new Car();
}
}
public class BikeFactory : VehicleFactory
{
public override Vehicle GetVehicle(string VehicleType)
{
return new Bike();
}
}
public class ClientClass
{
public void Main()
{
//Create Factories
BikeFactory BikeFactoryObj = new BikeFactory();
CarFactory CarFactoryObj = new CarFactory();
//create Vehicles from factories. If wanted they can be casted to the inherited type.
Vehicle VehicleObj=BikeFactoryObj.GetNewVehicle();
Bike BikeObj = (Bike)BikeFactoryObj.GetVehicle();
Car CarObj = (Car)CarFactoryObj.GetVehicle();
//They are all inherited from Vehicle so can be used in a list of Vehicles
List<Vehicle> Vehicles=new List<Vehicle>()
{
VehicleObj,
BikeObj,
CarObj
}
}
}
公共抽象类车辆工厂
{
公共摘要Vehicle GetVehicle(字符串VehicleType)
}
公共级汽车制造厂:汽车制造厂
{
公共超控车辆GetVehicle(字符串车辆类型)
{
归还新车();
}
}
公共级自行车工厂:车辆工厂
{
公共超控车辆GetVehicle(字符串车辆类型)
{
归还新自行车();
}
}
公共类ClientClass
{
公共图书馆
{
//创建工厂
BikeFactory BikeFactoryObj=新的BikeFactory();
CarFactory CarFactoryObj=新的CarFactory();
//从工厂创建车辆。如果需要,可以将其铸造为继承类型。
Vehicle VehicleObj=BikeFactoryObj.GetNewVehicle();
Bike BikeObj=(Bike)BikeFactoryObj.GetVehicle();
Car CarObj=(Car)CarFactoryObj.GetVehicle();
//它们都是从车辆继承的,因此可以在车辆列表中使用
列出车辆=新列表()
{
车辆OBJ,
比基奥布,
卡罗布
}
}
}
<
var myVehicle = new Vehicle();
public abstract class TaxComputer {
protected abstract Calculator getCalculator();// Factory method
public void registerIncome(){
//...
}
public Amount computeTax(){
Calculator alculator = getCalculator();
//... Tax computation logic using abstract Calculator
// Note: Real Calculator logic has not been written yet
return tax;
}
}
public interface Calculator {
Amount add(Amount a, Amount b);
Amount subtract(Amount a, Amount b);
Amount multiply(Amount a, double b);
Amount roundoff(int nearestAmount);
// ...
}
public class YenTaxComputer extends TaxComputer {
@Override
protected Calculator getCalculator() {
return new YenCalculator();
}
}
public class YenCalculator implements Calculator {
@Override
public Amount add(Amount a, Amount b) {
/*Yen specific additions and rounding off*/
}
@Override
public Amount subtract(Amount a, Amount b) {/*...*/ }
@Override
public Amount multiply(Amount a, double b) {/*...*/ }
@Override
public Amount roundoff(int nearestAmount) {/*...*/ }
}
public class TaxClient {
public static void main(String[] args) {
TaxComputer computer = new YenTaxComputer();//
computeTax(computer);
}
/** A PLACE HOLDER METHOD FOR DEMO
*/
private static void computeTax(TaxComputer computer) {
Amount tax = computer.computeTax();
Amount Payment = ...
//...
}
}