Answered by:
Factory Pattern - questions

Question
-
I'm refactoring an API library and have a small problem.
An existing class Session exposes a static Create method that returns a new instance of a Session.
I'm refactoring the code so Session is now an implementation of a new interface ISession.
Of course interfaces cannot define static members so how should I expose this Create method using the new interface based design?
Should I introduce a new static class SessionFactory? should that class be generic and create an instance of Session (or whatever class we want that implements ISession)?
Thx
Answers
-
A static Create method is a creational pattern so it doesn't fit into an interface. I think it is important to separate the concerns altogether. An interface is for separating implementation details. Interfaces aren't designed for creation (and shouldn't even have any bearing on such things) although some people like to create interfaces for creating other things, for some reason.
I would recommend you review what this Create method is doing. If it is simply newing up some object then replace that concept with DI. If Session requires complex initialization then it might not make sense to have it as an interface at all because interfaces are contracts, not implementation details. If Create is simply creating a complex instance of a session then the creation goes with the actual type being created, not the interface, so it becomes an implementation detail of however you create objects (DI or something else). The interface itself wouldn't have any concept of "creation".
If the Create method is more of an initialization method then expose an Initialize method from the interface. Client code would create the type directly and then call its Initialize method to allow it to be set up. If the initialization is generic and not really tied to the implementation then you could also just use an extension method on the interface instead.
If Create takes some configuration options in and returns an appropriate implementation (e.g. XmlReader) then it is probably best as a separate class that knows how to find implementations and select the best one. It isn't part of the contract that the app uses so it wouldn't go with the interface.
Michael Taylor http://www.michaeltaylorp3.net
- Proposed as answer by Wendy ZangMicrosoft contingent staff Wednesday, March 27, 2019 9:33 AM
- Marked as answer by Alberto PoblacionMVP Friday, April 5, 2019 9:59 AM
-
I have done things similar to what you are doing in the past. You have a few options... some of which were posted by Michael Taylor.
Personally however, I prefer to use an abstract class for situations like the one you describe. The abstract class can have your static "Create" method. You may have the abstract class based on an interface or you can have interfaces that are meant to be used with your abstract class (I have done both of these). From your "create" method you can call members of the interface, or you can have the necessary methods as abstract or virtual methods in your abstract class. Specifically, you can have the derived classes do all of their own initialization in the constructor; OR you can create an abstract initialization method. If you have initialization that is common to all, you can provide a base (virtual) method which can be overridden. Like Michael said, you should make choices based on your specific needs.
- Proposed as answer by Wendy ZangMicrosoft contingent staff Wednesday, March 27, 2019 9:33 AM
- Marked as answer by Alberto PoblacionMVP Friday, April 5, 2019 9:59 AM
All replies
-
A static Create method is a creational pattern so it doesn't fit into an interface. I think it is important to separate the concerns altogether. An interface is for separating implementation details. Interfaces aren't designed for creation (and shouldn't even have any bearing on such things) although some people like to create interfaces for creating other things, for some reason.
I would recommend you review what this Create method is doing. If it is simply newing up some object then replace that concept with DI. If Session requires complex initialization then it might not make sense to have it as an interface at all because interfaces are contracts, not implementation details. If Create is simply creating a complex instance of a session then the creation goes with the actual type being created, not the interface, so it becomes an implementation detail of however you create objects (DI or something else). The interface itself wouldn't have any concept of "creation".
If the Create method is more of an initialization method then expose an Initialize method from the interface. Client code would create the type directly and then call its Initialize method to allow it to be set up. If the initialization is generic and not really tied to the implementation then you could also just use an extension method on the interface instead.
If Create takes some configuration options in and returns an appropriate implementation (e.g. XmlReader) then it is probably best as a separate class that knows how to find implementations and select the best one. It isn't part of the contract that the app uses so it wouldn't go with the interface.
Michael Taylor http://www.michaeltaylorp3.net
- Proposed as answer by Wendy ZangMicrosoft contingent staff Wednesday, March 27, 2019 9:33 AM
- Marked as answer by Alberto PoblacionMVP Friday, April 5, 2019 9:59 AM
-
I have done things similar to what you are doing in the past. You have a few options... some of which were posted by Michael Taylor.
Personally however, I prefer to use an abstract class for situations like the one you describe. The abstract class can have your static "Create" method. You may have the abstract class based on an interface or you can have interfaces that are meant to be used with your abstract class (I have done both of these). From your "create" method you can call members of the interface, or you can have the necessary methods as abstract or virtual methods in your abstract class. Specifically, you can have the derived classes do all of their own initialization in the constructor; OR you can create an abstract initialization method. If you have initialization that is common to all, you can provide a base (virtual) method which can be overridden. Like Michael said, you should make choices based on your specific needs.
- Proposed as answer by Wendy ZangMicrosoft contingent staff Wednesday, March 27, 2019 9:33 AM
- Marked as answer by Alberto PoblacionMVP Friday, April 5, 2019 9:59 AM
-