创建者在工厂模式中的作用 [英] Role of Creator in Factory Pattern

查看:76
本文介绍了创建者在工厂模式中的作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为工厂类定义抽象类/接口的作用,这是我在网络上所有教程中经常看到的东西。有人可以说明一下CreatorInterface的重要性吗? 参考工厂模式的UML图

I couldn't understand the role of defining an abstract class / interface for the factory class, which is something i always see in all tutorials on the web. Can somebody please put some light on the importance of CreatorInterface ? Reference UML Diagram of the Factory Pattern

以代码形式输入,这是我所拥有的:

To put in code form, here's what i have :

代码示例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添加抽象类的原因是什么?在我看来,添加抽象类对于Abstract Factory方法是有意义的。 [如果我错了,请纠正我]

The above code doesn't contain any abstract class for the 'VehicleFactory' class. But it works fine. Now, what can be the reasons for adding an abstract class for the 'VehicleFactory' ? In my view adding an abstract class will make sense for the Abstract Factory method. [Please correct me if i'm wrong]

由GoF定义:


定义用于创建对象的接口,但让子类决定
实例化哪个类。工厂方法允许类推迟用于子类化的
实例化。

Define an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses.

据我所知,核心问题模式背后的陈述是,您希望创建不同类的实例,而又不将创建逻辑暴露给使用者。 如果我在这里遇到任何问题,请告诉我。由于我在网上看到的例子,我在这里也有些困惑。例如,在 Wiki 上,Php和C#示例。我可以在C#示例中消化模式的要求,而在PHP示例中则不能。无论如何,下面的语句将帮助您清楚地理解我的问题。

As far as i could understand, the core problem statement behind the pattern is that you want to create instances of different classes, without exposing the creation logic to the consumer. Please let me know if i'm getting anything wrong here. I am a little confused here too, because of the examples i see on the web. For e.g on Wiki, the Php and C# examples. I could digest the requirement of the pattern in C# example, but not in PHP example. Anyways, below statements will help you to understand my question clearly.

例如,我们的库中有两个车辆类Bike和Car,它们都有车辆模型数。自行车型号以 BK开头,汽车型号以 CR开头。现在,我们希望根据车辆型号返回任何一个类的实例,而无需将逻辑暴露给客户端。 [注意,这是一个更新的方案,我提出来是因为较早的方案决定类的逻辑较弱,并且对字符串的使用造成了混乱。]

For instance, we have two vehicle classes Bike and Car in our library, and both of them has vehicle model number. The Bike model number starts with "BK" and car model numbers start with "CR". Now, we wish to return instance of either of the classes depending of the Vehicle Model Number, without exposing the logic to the client. [Note This is an updated scenario, i am putting up since the earlier one had a weak logic of deciding the class, and created confusion over the use of string]

因此我们可以创建一个车辆工厂类,该类公开一个返回适当车辆实例的静态方法。

So we can create a vehicle factory class, which exposes a static method that returns the appropriate vehicle instance.

如果已知选择逻辑,客户,那么我可能不需要模式本身。因此,可能看起来像:

If selection logic is to be known to the client, then i might not have needed the pattern itself. So, the could would look like :

代码示例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();
        }
    }
}

工厂模式让我简单通过创建工厂向客户端隐藏创建逻辑。因此,客户现在只需要调用Factory的create方法,即可获得相应的类实例。现在,代码将如下所示。

The Factory Pattern let's me simply hide the creational logic from the client by creating a factory. Thus the Client now just needs to call the Factory's create method, and he'll get the appropriate class instance in return. Now the code will look like.

代码示例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");
    }
}

现在的问题是抽象工厂class

添加抽象工厂类的一个好处是,我从讨论中了解到,那么Client将能够覆盖 GetVehicle方法以覆盖逻辑。对于他可能创建了更多车辆类别的情况,例如卡车。但是即使在这种情况下,如果他想覆盖所有三个方法,即自行车,汽车和卡车的工厂方法,他将不会拥有完整的逻辑,因为创建自行车和汽车的逻辑是用工厂方法编写的。尽管他将能够为所有新车型创建新逻辑。

Now the question comes about the abstract factory class
One benefit of adding an abstract factory class, which i understood from the discussion is that the Client will then be able to override the 'GetVehicle' method to override the logic. For a case where he might have created more vehicle classes for example a 'Truck'. But even in this case, if he want's to override the factory method for all three namely Bike, Car and Truck, he will not be have the entire logic with him as the logic for Bike and Car creation is written in Factory method. Although he will be able to create a new logic for all his new vehicle types. Can someone please put some light on this ?

我想在这里提出的更多一点是,这个问题是关于工厂模式的,我确实知道摘要工厂模式将需要一个抽象工厂,因为在抽象工厂模式中,我们正在创建工厂工厂。但是在工厂模式下,我们只有一个对象工厂,那为什么我们需要一个工厂接口呢?

I more point i want to make here is that This question is regarding the Factory Pattern, i do understand that Abstract Factory pattern will require an Abstract Factory, since in Abstract Factory pattern we're creating Factory of Factories. But in Factory pattern we just have a factory of objects, then why do we need an interface for a factory ?

在此先感谢! :-)

推荐答案

@Yair Halberstadt ...为什么我比静态工厂更喜欢工厂方法... 。两者都有不同的目的。静态工厂是一个代码块,它(仅)收集对象层次结构的实例化代码(很容易使人相信该名称)。但是它的性质是静态的(尽管可以在实例级别编写),这意味着它在编译时受到约束。当然,我们可以扩展静态工厂,但主要是作为补丁代码。 (大多数情况下,在客户端框架上扩展不是首选。)

@Yair Halberstadt "...Why should i prefer the Factory method over the Static Factory ...". Both serve different purpose. Static factory is a code block which (just) collects the instantiation code for an object hierarchy (it is easy to get convinced about the name). But its nature is static (though can be written at instance level) meaning it gets bound at compile time. off course we can extend static factory but mainly as a patch code. (mostly not preferred at framework level for clients to extend.)

相比之下,Factory方法对于编写常见的业务逻辑而不指定具体的受益人类型很有用客户将在以后的日期写信。

In contrast Factory method is useful for writing common business logic without specifying the concrete beneficiary types which clients will write on later dates.

一个虚构的示例(假设普遍纳税计算)-

A fictitious example (with assumption of universal Tax computation)-

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);
    // ...
}

我所有的税法实施都在指提取计算器以使用 Amount 进行操作。目前仅需要抽象计算器。计税计算机准备就绪后,可以发布它以供客户端扩展(在抽象类上具有扩展点,并具有挂钩工厂方法)。

My all Tax rule implementations are referring to abstract Calculator for operations using Amount. It requires only abstract Calculator at this time. Once the Tax computer is ready, It can be published for clients to extend (With extension point at abstract classes and hook factory method).

特定客户端可以将其扩展至计算日元(没有小数点)或美元/英镑等,甚至是按照本地规则在每次操作后四舍五入的计算器(例如下一个10卢比)。

Specific client can extend it to computations for Yen (Does not have decimal point) or Dollar/ Pound etc or even calculators which round off (e.g. to next 10 Rupees) after every operation as per local rule.

USDollarTaxCalculator将以其自己的操作规则扩展它的方式(但不能也不必重新定义税收规则)

Same way USDollarTaxCalculator will extend it with their own rules for operations (but can not and need not redefine Tax rules)

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) {/*...*/  }
}

工厂方法中,重点不是隐藏创建逻辑,但让客户端可以扩展

In factory method point is not about hiding creation logic but keeping extensions possible for clients.

客户端看起来像

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

此处要注意的要点


  1. 客户端不使用工厂方法 getCalculator()

  2. Creator /工厂的具体实例可以通过静态工厂/反射等创建。可以从系统变量,平台,语言环境等中进行选择。

  3. 这种设计模式具有其自身的缺点/成本,例如并行类层次结构(YenTaxComputer仅负责创建实例)。没有免费的东西。

这篇关于创建者在工厂模式中的作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆