Especially in unittests we use this "design pattern" I call "get class from class level"
framworktest.py:
class FrameWorkHttpClient(object):
....
class FrameWorkTestCase(unittest.TestCase):
# Subclass can control the class which gets used in get_response()
HttpClient=FrameWorkHttpClient
def get_response(self, url):
client=self.HttpClient()
return client.get(url)
mytest.py:
class MyHttpClient(FrameWorkHttpClient):
....
class MyTestCase(FrameWorkTestCase):
HttpClient=MyHttpClient
def test_something(self):
response=self.get_response()
...
The method get_response()
gets the class from self
not by importing it. This way a subclass can modify the class and use a different HttpClient
.
What's the name of this (get class from class level) "design pattern"?
Is this a way of "inversion of control" or "dependency injection"?
I believe this has the same purpose as just simple polymorphism implemented using Python-specific syntax. Instead of having a virtual method returning a new instances, you have the instance type stored as "an overridable variable" in a class/subclass.
This can be rewritten as a virtual method (sorry I am not fluent in Python so this is just pseudocode)
then in the subclass, you change the implementation of the method to return a different type:
If you want to call this a pattern, I would say it is similar to Strategy GoF pattern. In your particular case, the algorithm being abstracted away is the creation of the particular HttpClient implementation.
And after second thought - as you stated, indeed this can be looked at as an IoC example.
You want to let the sub classes decide which class to instantiate.
This is what the factory method pattern already offers:
Your solving the same problem by replacing a variable of the parent class. It works but your solution has at least two drawbacks (compared to the classic pattern):
HttpClient
then invokeget_response
)I'm not exactly a design pattern 'Guru', but to me it looks a bit like the Template Method Pattern. You are defining the 'skeleton' of the
get_response
method in your base class, and leaving one step (defining which class to use) to the subclasses.If this can be considered the template pattern, it is an example of inversion of control.
Your code is very similar to Factory method pattern. The only difference is that your variant uses factory class variable instead of factory method.