本文介绍了没有开关或If/Then的工厂模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一个简单的示例,说明如何实现工厂类,但使用Switch或If-Then语句.我可以找到的所有示例都使用一个.例如,如何修改这个简单的示例(如下),以使实际工厂不依赖于Switch?在我看来,该示例违反了打开/关闭"原理.我希望能够添加具体的类(经理",文员",程序员"等),而无需修改工厂类.

I'm looking for a simple example of how to implement a factory class, but without the use of a Switch or an If-Then statement. All the examples I can find use one. For example, how could one modify this simple example (below) so that the actual factory does not depend on the Switch? It seems to me that this example violates the Open/Close principle. I'd like to be able to add concrete classes ('Manager', 'Clerk', 'Programmer', etc) without having to modify the factory class.

谢谢!

class Program
{
    abstract class Position
    {
        public abstract string Title { get; }
    }

    class Manager : Position
    {
        public override string Title
        {
            get  { return "Manager"; }
        }
    }

    class Clerk : Position
    {
        public override string Title
        {
            get { return "Clerk"; }
        }
    }

    class Programmer : Position
    {
        public override string Title
        {
            get { return "Programmer"; }
        }
    }

    static class Factory
    {
        public static Position Get(int id)
        {
            switch (id)
            {
                case 0: return new Manager();
                case 1: return new Clerk();
                case 2: return new Programmer();
                default: return new Programmer();
            }
        }
    }

    static void Main(string[] args)
    {
        for (int i = 0; i <= 2; i++)
        {
            var position = Factory.Get(i);
            Console.WriteLine("Where id = {0}, position = {1} ", i, position.Title);
        }
        Console.ReadLine();
    }
}

更新:

哇!谢谢大家!我学到了很多东西.收集所有反馈后,我混合了一些答案并提出了答案.我愿意就更好的方法进行进一步的对话.

Wow! Thanks everyone! I have learned a ton. After revewing all the feedback, I blended a few of the answers and came up with this. I'd be open to further dialog about a better way to do this.

class Program
{

    public interface IPosition
    {
        string Title { get; }
    }

    class Manager : IPosition
    {
        public string Title
        {
            get { return "Manager"; }
        }
    }

    class Clerk : IPosition
    {
        public string Title
        {
            get { return "Clerk"; }
        }
    }

    class Programmer : IPosition
    {
        public string Title
        {
            get { return "Programmer"; }
        }
    }

static class PositionFactory
{
    public static T Create<T>() where T : IPosition, new()
    {
        return new T();
    }
}


static void Main(string[] args)
    {

        IPosition position0 = PositionFactory.Create<Manager>();
        Console.WriteLine("0: " + position0.Title);

        IPosition position1 = PositionFactory.Create<Clerk>();
        Console.WriteLine("1: " + position1.Title);

        IPosition position2 = PositionFactory.Create<Programmer>();
        Console.WriteLine("1: " + position2.Title);

        Console.ReadLine();
    }
}

另一个

还可以使用未知类型创建Interface的实例:

It's also possible to create an instance of the Interface using an unknown type:

static class PositionFactory
{
   public static IPosition Create(string positionName)
    {       
        Type type = Type.GetType(positionName);
        return (IPosition)Activator.CreateInstance(type);
    }
}

然后可以这样称呼:

IPosition position = PositionFactory.Create("Manager");
Console.WriteLine(position.Title);

推荐答案

如何解决(不需要字典,请注意,如果尝试Create<Position>(),将会出现语法错误):

How about this (no Dictionary required and note that you will get an syntax error if your try to Create<Position>()):

编辑-更新为使用显式实现的IPosition接口.只有IPosition实例可以访问成员函数(例如<implementation of Manager>.Title将不会编译).

EDIT - Updated to use an IPosition interface implemented explicitly. Only instances of IPosition can access the member functions (e.g. <implementation of Manager>.Title will not compile).

EDIT#2 工厂.正确使用接口时,Create应该返回IPosition而不是T.

EDIT #2 Factory.Create should return an IPosition not T when using the interface properly.

using System;
using System.Collections.Generic;

class Program
{
    interface IPosition
    {
        string Title { get; }
        bool RequestVacation();
    }

    class Manager : IPosition
    {
         string IPosition.Title
        {
            get { return "Manager"; }
        }

        bool IPosition.RequestVacation()
        {
            return true;
        }
    }

    class Clerk : IPosition
    {
        int m_VacationDaysRemaining = 1;

        string IPosition.Title
        {
            get { return "Clerk"; }
        }

        bool IPosition.RequestVacation()
        {
            if (m_VacationDaysRemaining <= 0)
            {
                return false;
            }
            else
            {
                m_VacationDaysRemaining--;
                return true;
            }
        }
    }

    class Programmer : IPosition
    {
        string IPosition.Title
        {
            get { return "Programmer"; }
        }

        bool IPosition.RequestVacation()
        {
            return false;
        }
    }

    static class Factory
    {
        public static IPosition Create<T>() where T : IPosition, new ()
        {
            return new T();
        }
    }

    static void Main(string[] args)
    {
        List<IPosition> positions = new List<IPosition>(3);
        positions.Add(Factory.Create<Manager>());
        positions.Add(Factory.Create<Clerk>());
        positions.Add(Factory.Create<Programmer>());

        foreach (IPosition p in positions) { Console.WriteLine(p.Title);  }
        Console.WriteLine();

        Random rnd = new Random(0);
        for (int i = 0; i < 10; i++)
        {
            int index = rnd.Next(3);
            Console.WriteLine("Title: {0}, Request Granted: {1}", positions[index].Title, positions[index].RequestVacation());
        }

        Console.ReadLine();
    }
}

这篇关于没有开关或If/Then的工厂模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-25 20:38