C# 创建者在工厂模式中的角色

C# 创建者在工厂模式中的角色,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() {

我无法理解为factory类定义抽象类/接口的作用,这是我在web上所有教程中经常看到的。有人能解释一下创作者界面的重要性吗

以代码形式来说,我有:

代码示例1

// 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 = ...
            //...
        }
    }