工厂设计模式 - 为什么需要接口?

问题描述 投票:6回答:6

我开始研究不同的设计模式,现在我专注于工厂设计模式。我看了一些例子,youtube tuturials和博客,我得到了最多,但我仍然没有得到为什么接口是必要的。

官方定义是:

定义用于创建对象的接口,但让子类决定实例化哪个类。 Factory Method允许类将实例化延迟到子类。

因此,界面似乎是工厂设计模式的重要组成部分,但是我发现在主方法中创建集合时实际的唯一原因。如果您不想要它,您可以删除它(查看下面的代码,可能的地方),它仍然像计划的那样工作。

using System;
using System.Collections.Generic;
using System.Collections;

namespace FactoryDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            var FordFiestaFactory = new FordFiestaFactory();
            var FordFiesta = FordFiestaFactory.CreateCar("Blue");
            Console.WriteLine("Brand: {0} \nModel: {1} \nColor: {2}", FordFiesta.Make, FordFiesta.Model, FordFiesta.Color);
            Console.WriteLine();


            //Inserted this later. Using a collection requires the Interface to be there.
            List<ICreateCars> Cars = new List<ICreateCars>();
            Cars.Add(new FordFiestaFactory());
            Cars.Add(new BMWX5Factory());

            foreach (var Car in Cars)
            {
                var ProductCar = Car.CreateCar("Red");
                Console.WriteLine("Brand: {0} \nModel: {1} \nColor: {2}", ProductCar.Make, ProductCar.Model, ProductCar.Color);
                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }

    public abstract class Car
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public string EngineSize { get; set; }
        public string Color { get; set; }
    }

    public class FordFiesta : Car
    {
        public FordFiesta()
        {
            Make = "Ford";
            Model = "Fiesta";
            EngineSize = "1.1";
        }
    }

    public class BMWX5 : Car
    {
        public BMWX5()
        {
            Make = "BMW";
            Model = "X5";
            EngineSize = "2.1";
        }
    }

    public interface ICreateCars
    {
        Car CreateCar(string color);
    }

    class FordFiestaFactory : ICreateCars
    {
        public Car CreateCar(string color)
        {
            return new FordFiesta() { Color = color };
        }
    }

    class BMWX5Factory : ICreateCars
    {
        public Car CreateCar(string color)
        {
            return new BMWX5(){ Color = color };
        }
    }
}

那我为什么需要那个接口呢?我阅读了多个抽象的解释,但我没有得到它,所以我更喜欢实际的答案。

提前致谢!

c# design-patterns factory factory-pattern
6个回答
7
投票

只要工厂的调用者不知道工厂的类型,接口(或抽象工厂基类,它实际上与有效的接口相同)就很有用。

您为自己的实际示例提供了基础,因此我将在此处添加我的解释,为什么在获得工厂列表时这不仅有用:

想象一下这种方法应该在适当时创建汽车,而不知道要创建什么类型的汽车(由工厂实施决定)。该方法查看Person对象,该对象具有OwnsCar属性,该属性最终决定是否应调用工厂方法:

public Car CreateCarForPerson(Person person, ICreateCars carType)
{
    if (person.OwnsCar) {
        return carType.CreateCar("red");
    } else {
        return null;
    }
}

以同样的方式,您也可以使用这样的工厂来创建任意数量的汽车:

public Car[] CreateAnyNumberOfCars(ICreateCars carType)
{
    var result = new List<Car>();
    for (int i = new Random().Next(100); i >= 0; i--) {
        result.Add(carType.CreateCar("blue"));
    }
    return result.ToArray();
}

注意这两种方法都不知道正在创建什么样的车型;他们使用的工厂只知道界面,但不是确切的类型。

因此,如果您希望能够提供不同的工厂实现,则可以为工厂声明一个通用接口。如果您的工厂仅用于使您的调用者远离目标构造函数的直接调用,则不需要工厂接口。


2
投票

您始终可以按照自己喜欢的方式应用设计模式。删除界面没有任何问题。但是,您应该考虑到删除界面会导致结构不太通用。

您使用factory pattern是因为您不希望您的调用代码(主函数)知道有关构造细节的任何信息。你不想知道FordFiest是什么。你只想要建造一辆汽车。如果它是福特嘉年华,那就这样吧。这个细节是工厂(及其子类)应该处理的东西。对?

如果您不希望您的代码依赖于特定的工厂,则需要一个由接口提供的额外抽象层,从而导致两个部分“分离”。如果您不介意将代码绑定到特定的工厂实现,则可以始终删除该接口。

希望我帮忙!


2
投票

当然你可以使用CarFactory创建衍生汽车类,但是那些想要支持汽车创造的人必须从CarFactory派生。在我看来,界面的目的是让谁可以更灵活地充当汽车工厂。这个概念是你需要做的就是在这个例子中成为一个CarFactory来实现ICreateCars接口。无需介绍交付的CarFactory基类的开销。

关键在于决定接受汽车工厂的功能的参数类型。 (或者存储CarFactory的成员的成员类型)如果你使用ICreateCars,那么任何想要创建汽车的人只需要实现该界面。如果你的参数类型是CarFactory,那么他们必须从CarFactory继承。


2
投票

嗯,不是真的 - 界面不是这种模式的组成部分。您可以像静态类甚至是普通类一样好地实现工厂。

只是使用接口通常是一个非常好的主意,大多数好的,基于组件的设计都会大量使用它。它被称为Interface based programming,其主要优点是它允许IoC容器并且它使您的代码可测试。

我个人而言,我几乎盲目地使用界面,甚至没有考虑过它......


0
投票

Factory Pattern的目的是抽象创建。在这种情况下,有可能与工厂交换正确的实现。

抽象可以通过.NET中的接口或抽象类来实现。

public interface ICreateCars
{
    Car CreateCar(string color);
}

构建结果(Car)可以是类或接口,只需看一下情况。如何建立它是工厂的工作。


0
投票

接口允许您记录有一组类,这些类遵循一组特定的多态方法,而无需创建继承层次结构来链接所有类。

如果没有Interfaces,设计人员将不得不创建一个他们都继承的人工基类。当Class需要实现两组不同的多态方法时,这就变得不可能了。

多重继承是语言设计者想要避免的,因为当类有两个父项时,不清楚应该调用哪些方法。除此之外,实现的人工继承总是很尴尬。

从根本上说,Interfaces允许您继承方法定义而不继承任何实现。

© www.soinside.com 2019 - 2024. All rights reserved.