Reflection in factory design patterns in Java or C#

前端 未结 2 2012
日久生厌
日久生厌 2021-01-25 21:13

I came across a term called reflection. It is a feature commonly used in factory design patterns. I had a hard time understanding the concept because I’m still learning how to p

相关标签:
2条回答
  • 2021-01-25 21:43

    Java version for this question

    Code:

    public class TestReflectionFactoryDesign {
    
        public static void main(String[] args) throws Exception {
            Person student = PersonFactory.getPersonWithFullQualifiedClassName("com.test.reflectionFactoryDesign.Student");
            student.say();
            Person teacher = PersonFactory.getPersonWithClass(Teacher.class);
            teacher.say();
            Person student2 = PersonFactory.getPersonWithName("student");
            student2.say();
        }
    }
    
    class Student implements Person {
        @Override
        public void say() {
            System.out.println("I am a student");
        }
    }
    
    class Teacher implements Person {
        @Override
        public void say() {
            System.out.println("I am a teacher");
        }
    }
    
    interface Person {
        void say();
    }
    
    class PersonFactory {
        // reflection, by full qualified class name
        public static Person getPersonWithFullQualifiedClassName(String personType) throws Exception {
            Class<?> personClass = Class.forName(personType);
            return getPersonWithClass(personClass);
        }
    
        // reflection, by passing class object
        public static Person getPersonWithClass(Class personClass) throws Exception {
            return (Person) personClass.newInstance();
        }
    
        // no reflection, the ordinary way
        public static Person getPersonWithName(String personType) {
            if (personType.equalsIgnoreCase("STUDENT")) {
                return new Student();
            } else if (personType.equalsIgnoreCase("TEACHER")) {
                return new Teacher();
            }
    
            return null;
        }
    }
    

    Output:

    I am a student
    I am a teacher
    I am a student
    
    0 讨论(0)
  • 2021-01-25 22:03

    I would never use reflection to implement Factory design pattern, unless there was a special case. The below code is a terrible way to implement the factory design pattern. But since you wanted to know "How" to use reflection for factory design pattern here's the example:

    namespace NaiveFactory
    {
    
        public interface Shape
        {
            void Draw();
        }
    
        public class Circle : Shape
        {
            public void Draw() { Console.WriteLine("Drawing Circle"); }
        }
    
        public class Rectangle : Shape
        {
            public void Draw() { Console.WriteLine("Drawing Rectangle"); }
        }
    
        public class ShapeFactory
        {
            public static Shape GetShape<T>() where T : Shape
            {
                return Activator.CreateInstance<T>();
            }
    
            public static Shape GetShape(string shapeName)
            {
                var assembly = Assembly.GetExecutingAssembly();
                var type = assembly.GetType(shapeName).FullName;
                return (Shape) Activator.CreateInstanceFrom(assembly.Location, type).Unwrap();
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                var shape = ShapeFactory.GetShape<Circle>();
                var shape2 = ShapeFactory.GetShape("NaiveFactory.Rectangle");
                shape.Draw();
                shape2.Draw();
                Console.ReadKey();
            }
        }
    }
    

    EDIT As per suggestion from @AlexeiLevenkov, I have added something close to Dependency injection and instantiating the Shape objects using Constructor Injection as well as with a method:

    namespace NaiveFactory
    {
        public interface IBoard
        {
            void InternalDraw(string str);
        }
    
        public class ConsoleBoard : IBoard
        {
            public void InternalDraw(string str) { Console.WriteLine(str); }
        }
    
        public class DebugBoard : IBoard
        {
            public void InternalDraw(string str) { Debug.WriteLine(str); }
        }
    
        public interface Shape
        {
            IBoard Board { get; set; }
            void Draw();
            void SetBoard(IBoard board);
        }
    
        public class Circle : Shape
        {
            public IBoard Board { get; set; }
    
            public Circle()
            {
    
            }
    
            public Circle(IBoard board)
            {
                Board = board;
            }
    
            public void Draw() { Board.InternalDraw("Drawing Circle"); }
    
            public void SetBoard(IBoard board)
            {
                Board = board;
            }
        }
    
        public class Rectangle : Shape
        {
            public IBoard Board { get; set; }
    
            public Rectangle()
            {
    
            }
    
            public Rectangle(IBoard board)
            {
                Board = board;
            }
    
            public void Draw() { Board.InternalDraw("Drawing Rectangle"); }
    
            public void SetBoard(IBoard board)
            {
                Board = board;
            }
        }
    
        public class ShapeFactory
        {
            private static Dictionary<Type, Type> _configurationData = new Dictionary<Type, Type>();
    
            public static Shape GetShape<T>() where T : Shape
            {
                return Activator.CreateInstance<T>();
            }
    
            public static void ConfigureContainer<T, U>()
            {
                _configurationData.Add(typeof(T), typeof(U));
            }
    
            public static Shape GetShape_UsingConstructorInjection(string shapeName)
            {
                var assembly = Assembly.GetExecutingAssembly();
                var type = assembly.GetType(shapeName);
                var constructor = type.GetConstructor(_configurationData.Keys.ToArray());
                if (constructor != null)
                {
                    var parameters = constructor.GetParameters();
                    return (from parameter in parameters where _configurationData.Keys.Contains(parameter.ParameterType) 
                            select Activator.CreateInstance(_configurationData[parameter.ParameterType]) into boardObj 
                            select (Shape) Activator.CreateInstance(type, boardObj)).FirstOrDefault();
                }
                return null;
            }
    
            public static Shape GetShape_UsingSetBoardMethod(string shapeName)
            {
                var assembly = Assembly.GetExecutingAssembly();
                var type = assembly.GetType(shapeName);
                var shapeObj = (Shape) Activator.CreateInstance(type);
                if (shapeObj != null)
                {
                    shapeObj.SetBoard((IBoard) Activator.CreateInstance(_configurationData[typeof (IBoard)]));
                    return shapeObj;
                }
    
                return null;
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                ShapeFactory.ConfigureContainer<IBoard, ConsoleBoard>();
                var shape = ShapeFactory.GetShape_UsingSetBoardMethod("NaiveFactory.Circle");
                var shape2 = ShapeFactory.GetShape_UsingConstructorInjection("NaiveFactory.Rectangle");
                shape.Draw();
                shape2.Draw();
                Console.ReadKey();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题