Это все еще фабричный метод?

Что делать, если мне не нужен специальный фабричный класс, и я хочу, чтобы конкретный клиент создавал нужные части. Клиент должен вызвать Hello() из этой части. Повсюду в центре внимания находится превращение фабричного метода в метод специального класса-создателя. Но здесь это прямо в клиенте. Это все еще шаблон фабричного метода, и правильно ли его использовать, как показано ниже?

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            AClient c1 = new ClientUsingPart1();
            c1.Foo();
            AClient c2 = new ClientUsingPart2();
            c2.Foo();
            Console.ReadKey();
        }
    }

    abstract class AClient
    {
        public AClient() { this.ipart = Create(); }

        public void Foo() { ipart.Hello(); }
        // many other methods
        // ...
        public abstract IPart Create();  // factory method
        IPart ipart;
    }

    class ClientUsingPart1 : AClient
    {
        public override IPart Create() { return new Part1(); }
    }

    class ClientUsingPart2 : AClient
    {
        public override IPart Create() { return new Part2(); }
    }

    interface IPart
    {
        void Hello();
    }

    class Part1 : IPart
    {
        public void Hello() { Console.WriteLine("hello from part1"); }
    }
    class Part2 : IPart
    {
        public void Hello() { Console.WriteLine("hello from part2"); }
    }

}

2 ответа

Решение

В соответствии с этим: Различия между абстрактным фабричным шаблоном и фабричным методом Кажется, код, который я разместил в оригинальном сообщении, показывает правильное использование фабричного метода. Ключ - фабричный метод - это просто метод класса, который также может быть единственным клиентом созданных объектов.

Или по-другому: фабричный метод не должен быть общедоступным и предоставлять созданные объекты внешнему миру. В моем примере метод Create() должен быть защищен.

В зависимости от того, чего именно вам нужно достичь, вы, вероятно, должны использовать некоторые из них для внедрения зависимостей с выбранным вами контейнером IoC; с StructureMap, Autofac, Unit, Ninject, Castle Windsor все очень популярны. После того, как ваш IoC-контейнер создал конкретные классы, он должен поддерживать такой синтаксис

foreach (var client in Container.Resolve<IEnumerable<AClient>>())
{
    client.Create();
}

Подробнее о том, как этого добиться с помощью StructureMap, вы можете прочитать здесь: Работает ли абстрактный класс с StructureMap, как интерфейс?

Другие вопросы по тегам