Factory pattern in C#: How to ensure an object instance can only be created by a factory class?

后端 未结 17 1511
小鲜肉
小鲜肉 2020-11-29 16:51

Recently I\'ve been thinking about securing some of my code. I\'m curious how one could make sure an object can never be created directly, but only via some method of a fact

相关标签:
17条回答
  • 2020-11-29 17:21

    Yet another (lightweight) option is to make a static factory method in the BusinessObject class and keep the constructor private.

    public class BusinessObject
    {
        public static BusinessObject NewBusinessObject(string property)
        {
            return new BusinessObject();
        }
    
        private BusinessObject()
        {
        }
    }
    
    0 讨论(0)
  • 2020-11-29 17:21

    So, it looks like what I want cannot be done in a "pure" way. It's always some kind of "call back" to the logic class.

    Maybe I could do it in a simple way, just make a contructor method in the object class first call the logic class to check the input?

    public MyBusinessObjectClass
    {
        public string MyProperty { get; private set; }
    
        private MyBusinessObjectClass (string myProperty)
        {
            MyProperty  = myProperty;
        }
    
        pubilc static MyBusinessObjectClass CreateInstance (string myProperty)
        {
            if (MyBusinessLogicClass.ValidateBusinessObject (myProperty)) return new MyBusinessObjectClass (myProperty);
    
            return null;
        }
    }
    
    public MyBusinessLogicClass
    {
        public static bool ValidateBusinessObject (string myProperty)
        {
            // Perform some check on myProperty
    
            return CheckResult;
        }
    }
    

    This way, the business object is not creatable directly and the public check method in business logic will do no harm either.

    0 讨论(0)
  • 2020-11-29 17:24

    Would appreciate hearing some thoughts on this solution. The only one able to create 'MyClassPrivilegeKey' is the factory. and 'MyClass' requires it in the constructor. Thus avoiding reflection on private contractors / "registration" to the factory.

    public static class Runnable
    {
        public static void Run()
        {
            MyClass myClass = MyClassPrivilegeKey.MyClassFactory.GetInstance();
        }
    }
    
    public abstract class MyClass
    {
        public MyClass(MyClassPrivilegeKey key) { }
    }
    
    public class MyClassA : MyClass
    {
        public MyClassA(MyClassPrivilegeKey key) : base(key) { }
    }
    
    public class MyClassB : MyClass
    {
        public MyClassB(MyClassPrivilegeKey key) : base(key) { }
    }
    
    
    public class MyClassPrivilegeKey
    {
        private MyClassPrivilegeKey()
        {
        }
    
        public static class MyClassFactory
        {
            private static MyClassPrivilegeKey key = new MyClassPrivilegeKey();
    
            public static MyClass GetInstance()
            {
                if (/* some things == */true)
                {
                    return new MyClassA(key);
                }
                else
                {
                    return new MyClassB(key);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-29 17:26

    Apart from what Jon suggested, you could also either have the factory method (including the check) be a static method of BusinessObject in the first place. Then, have the constructor private, and everyone else will be forced to use the static method.

    public class BusinessObject
    {
      public static Create (string myProperty)
      {
        if (...)
          return new BusinessObject (myProperty);
        else
          return null;
      }
    }
    

    But the real question is - why do you have this requirement? Is it acceptable to move the factory or the factory method into the class?

    0 讨论(0)
  • 2020-11-29 17:31
        public class HandlerFactory: Handler
        {
            public IHandler GetHandler()
            {
                return base.CreateMe();
            }
        }
    
        public interface IHandler
        {
            void DoWork();
        }
    
        public class Handler : IHandler
        {
            public void DoWork()
            {
                Console.WriteLine("hander doing work");
            }
    
            protected IHandler CreateMe()
            {
                return new Handler();
            }
    
            protected Handler(){}
        }
    
        public static void Main(string[] args)
        {
            // Handler handler = new Handler();         - this will error out!
            var factory = new HandlerFactory();
            var handler = factory.GetHandler();
    
            handler.DoWork();           // this works!
        }
    
    0 讨论(0)
提交回复
热议问题