简体   繁体   English

我正在研究抽象工厂模式,为 class 的每种类型都有一个抽象工厂是一种好的做法吗?

[英]I am studying the abstract factory pattern, is it good practice to have an abstract factory for each type of class?

I am implementing the abstract factory pattern, is there a way to not use an abstract class for different class types?我正在实现抽象工厂模式,有没有办法不对不同的 class 类型使用抽象 class?

The structure of my classes is like this: Structure Project我的课程结构是这样的: Structure Project

Rectangle.cs and Square.cs implement IShape.cs: Structure Class for AbstractShapeFactory Rectangle.cs 和 Square.cs 实现 IShape.cs: Structure Class for AbstractShapeFactory

namespace FactoryMethod.Patterns.Creational.Factory.Shape
{
    public interface IShape
    {
        public void Draw();
    }
}
namespace FactoryMethod.Patterns.Creational.Factory.Shape.Normal
{
    public class Rectangle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("Normal Rectangle");
        }
    }
}

NormalShapeImp.cs and RoundedShapeImp.cs implement AbstractShapeFactory.cs NormalShapeImp.cs 和 RoundedShapeImp.cs 实现 AbstractShapeFactory.cs

The AbstractShapeFactory.cs class looks like this: AbstractShapeFactory.cs class 看起来像这样:

namespace FactoryMethod.Patterns.Creational.Factory
{
    public enum TypeShape
    {
        Square = 1,
        Rectangle = 2
    }

    public abstract class AbstractShapeFactory
    {
        public abstract IShape CreateShape(TypeShape typeShape);
    }
}


public class NormalShapeImp : AbstractShapeFactory
    {
        public override IShape CreateShape(TypeShape typeShape)
        {
            return typeShape switch
            {
                TypeShape.Square => new Square(),
                TypeShape.Rectangle => new Rectangle(),
                _ => new Square(),
            };
        }
    }

The AbstractPaymentFactory.cs class looks like this: AbstractPaymentFactory.cs class 看起来像这样:

namespace FactoryMethod.Patterns.Creational.Factory
{
    public enum TypePayment
    {
        Google = 1,
        Paypal = 2
    }

    public abstract class AbstractPaymentFactory
    {
        public abstract IPayment CreatePayment(TypePayment typePayment);
    }
}

namespace FactoryMethod.Patterns.Creational.Factory.Payment
{
    public class LocalPaymentImp : AbstractPaymentFactory
    {
        public override IPayment CreatePayment(TypePayment typePayment)
        {
            return typePayment switch
            {
                TypePayment.Google => new LocalGooglePayment(),
                TypePayment.Paypal => new LocalPaypal(),
                _ => new LocalGooglePayment(),
            };
        }
    }
}

I have two abstract factory classes AbstractPaymentFactory.cs Y AbstractShapeFactory.cs我有两个抽象工厂类 AbstractPaymentFactory.cs Y AbstractShapeFactory.cs

And I have a FactoryProducer.cs class that is in charge of returning one or the other Factory.我有一个 FactoryProducer.cs class 负责返回一个或另一个工厂。

namespace FactoryMethod.Patterns.Creational.Factory
{
    public class FactoryProducer
    {
        public static AbstractPaymentFactory GetPaymentFactory(bool isLocal)
        {
            if (isLocal)
                return new LocalPaymentImp();

            return new ForeignPaymentImp();
        }

        public static AbstractShapeFactory GetShapeFactory(bool isRounded)
        {
            if (isRounded)
                return new RoundedShapeImp();

            return new NormalShapeImp();
        }
    }
}

I have my Program.cs class as follows:我的 Program.cs class 如下:

static void Main(string[] args)
        {
            #region Pattern Abstract Factory

            /* Factory Payment */
            Console.WriteLine("Factory Payment:");
            Console.WriteLine("Select Type Payment:");
            Console.WriteLine("1- Google (default)");
            Console.WriteLine("2- Paypal");

            int inputType = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Select Account:");
            Console.WriteLine("0- Local");
            Console.WriteLine("1- Foreign (default)");
            bool opAccount = Console.ReadLine() == "0";

            AbstractPaymentFactory factoryPayment = FactoryProducer.GetPaymentFactory(opAccount);
            IPayment payment = factoryPayment.CreatePayment((TypePayment)inputType);
            payment.DoPayment();
            Console.WriteLine("");

            /* End Factory Payment */


            /* Factory Shape */
            Console.WriteLine("Factory Payment:");
            Console.WriteLine("Select Type Shape");
            Console.WriteLine("1- Square (default)");
            Console.WriteLine("2- Rectangle");

            int inputTypeShape = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Select:");
            Console.WriteLine("0- Normal (default)");
            Console.WriteLine("1- Rounded");
            bool opShape = Console.ReadLine() == "0";

            AbstractShapeFactory factoryShape = FactoryProducer.GetShapeFactory(opShape);
            IShape shape = factoryShape.CreateShape((TypeShape)inputTypeShape);
            shape.Draw();

            /* End Factory Shape */

            #endregion
        }

Is what I am doing a good practice?我正在做的事情是好的做法吗? Is there another way to not create a abstract factory for different types?还有另一种不为不同类型创建抽象工厂的方法吗?

First of all, always ask yourself how the pattern is helping you, and if the benefit outweigh the added complexity.首先,始终问问自己该模式对您有何帮助,以及收益是否超过增加的复杂性。 Do not use patterns just because you have read about them.不要仅仅因为阅读过它们就使用模式。 For a toy example like this the code could probably be condensed to a switch-statement:对于像这样的玩具示例,代码可能会被压缩为一个 switch 语句:

var shape = (shapeType, isRounded) switch
{
    (1, false) => new Square(),
    (1, true) => new RoundedSquare(),
    (2, false) => new Rectangle(),
    (2, true) => new RoundedRectangle(),
};

This involves much less code, so would tend to be easier to read.这涉及更少的代码,因此往往更容易阅读。

Factories and abstract factories provide additional layer of abstraction.工厂和抽象工厂提供额外的抽象层。 This is sometimes needed, say if you have a large amount of shapes, or want to reduce the dependencies from components.这有时是需要的,比如如果你有大量的形状,或者想减少组件的依赖性。 But you should generally be careful about your abstraction layers since these can be 'leaky'.但是您通常应该小心您的抽象层,因为它们可能会“泄漏”。 Consider for example if you want to create a circle or a line, what would a rounded line be?考虑例如,如果你想创建一个圆或一条线,圆角线是什么? or a non-round circle?还是非圆圈? For an intentional example of over-abstraction, see fizzbuzz enterprise edition .有关过度抽象的故意示例,请参阅fizzbuzz 企业版

You might also want to read up on the concept of Dependency Injection (DI), Inversion Of Control (IoC) and associated IoC libraries.您可能还想阅读依赖注入 (DI)、控制反转 (IoC) 和相关 IoC 库的概念。 This can help resolve dependency chains, ie classes takes dependencies as constructor parameters.这可以帮助解决依赖链,即类将依赖作为构造函数参数。 At startup you register what dependencies should be used in the container and request some object of a specific type from the container, the container will then figure out how to create all the dependencies.在启动时,您注册应该在容器中使用的依赖项并从容器中请求一些特定类型的 object,然后容器将弄清楚如何创建所有依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM