开发者

Factory Method pattern and public constructor

开发者 https://www.devze.com 2022-12-29 14:21 出处:网络
Im making a factory method that returns new instances of my objects. I would like to prevent anyone using my code fro开发者_运维技巧m using a public constructor on my objects. Is there any way of doin

Im making a factory method that returns new instances of my objects. I would like to prevent anyone using my code fro开发者_运维技巧m using a public constructor on my objects. Is there any way of doing this?

How is this typically accomplished:

public abstract class CarFactory
{
  public abstract ICar CreateSUV();
}

public class MercedesFactory : CarFactory
{
  public override ICar CreateSUV()
  {
    return new Mercedes4WD();
  }
}

I then would like to limit/prevent the other developers (including me in a few months) from making an instance of Mercedes4WD. But make them call my factory method. How to?


you can make the class Mercedes4WD a internal class with an internal constructor which will stop it being instantiated from outside of the library which contains the factory.

You might be better having a factory method on your class which produces the instance, which you could call from your factory class, but that is not that different from just 'newing' it up.

You could also have the Mercedes4WD on one assembly, the factory in another and your code in a third, then the factory assembly could be a friend of the Mercedes4WD assembly so it could create the instances, but the main code would not be so it couldn't. That would reduce the scope under which the instances could be created, but everything would a bit more complex.

Really you need to provide some more information. when you say you would like to stop people constructing later, are you talking about other devs working in the same codebase? If so there is not really that much you can do. You might be able to do some checking in the constructor to see if the next method up in the stack is the factory's method and throw an exception if not, but I'm not sure that is a great idea...

The real question is why do you want to do this?


You really want the C++ equivalent of friend classes, but C# does not have them. You can always make the constructor private and add a static factory method to Mercedes4WD. This would prevent "accidental" direct construction:

public class Mercedes4WD : ICar
{
    private Mercedes4WD()
    {
        // ...
    }

    public static Mercedes4WD Create()
    {
        return new Mercedes4WD();
    }
}

public abstract class CarFactory
{
    public abstract ICar CreateSUV();
}

public class MercedesFactory : CarFactory
{
    public override ICar CreateSUV()
    {
        return Mercedes4WD.Create();
    }
}


You can define the default contructor of your class Mercedes4WD as internal. So the default constructor can only be called within the assembly where the type Mercedes4WD is defined.


for a factory method, make the constructor private but it looks like you are actually implementing the factory pattern


Keep the constructors internal or implement the interfaces explicitly, so that the classes can not be instantiated directly.


It sounds like your general question is how a class can make a method available to one or more other classes, without making it available to all classes in the assembly. Assuming that no object exposes its direct constructors in any form, you can achieve the effect you're looking for using static delegates.

Suppose class Foo wants to expose its static Wozzle method to class Bar but nobody else. Bar should have a static delegate which it uses to call Foo.Wozzle. If Bar needs to call Foo.Wozzle but the delegate hasn't been created yet, it should create a new object of a type known only to Bar (call it the "token") and pass it to static method Foo.BarRequestsWozzle. That method should create a static delegate for Foo.Wozzle if one hasn't yet been created, and pass that delegate, along with the passed-in token object, to Bar.FooSuppliesWozzle. That method should check whether the type of the passed-in token matches the one that was given to BarRequestsWozzle and, if so, set the delegate appropriately. Foo doesn't give its Wozzle method to anyone but Bar, nobody can create the proper token type except Bar, and Bar doesn't give his token to anyone but Foo.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号