I haven't quite found an answer to this specific question on Stack Overflow, so I'm posting it here.
I have a factory class which generates a Database handling object from an abstract class, depending on which database you need (see code).
My question is this; I have some generic methods which are ONLY applicable to the database handler...so I would think it NOT appropriate to put them into their own module...but I'm not sure where the appropriate place to put them is.
Putting them in the abstract class certainly works, but I don't know if thats the accepted place for them.
abstract class
class DBHandlerAbstract(object): # ABSTRACT CLASS ---
__metaclass__ = abc.ABCMeta
# I HAVE TO BE OVERRIDDEN
@abc.abstractmethod
def open(self):
raise NotImplementedError
# I HAVE TO BE OVERRIDDEN
@abc.abstractmethod
def close(self):
raise NotImplementedError
# SHOULD THIS GF GO HERE OR ELSEWHERE???
def _check_host(self):
print 'this will be the same for all dbhandler objects'
factory class
class DBHandler(object): # FACTORY CLASS ---
"""
This is a factory class that will call and return a subclass.
It is NOT an abstract class.
The objects classes that are instantiated by this factory will be
subclasses of DBHandler
"""
@staticmethod
def handler(service, *args, **kwargs):
# Microsoft SQL (mssql)
if re.match("^(\s*)ms(\s*)sql.*$", str(service.lower())):
return DBHandler_MSSQL(*args, **kwargs)
# MySQL
elif re.match("^(\s*)my(\s*)sql.*$", str(service.lower())):
return DBHandler_MYSQL(*args, **kwargs)
else:
log.error(MSG.DBHandlerNotProvided())
raise TypeError('DBHandler service not provided.')
functional class
class DBHandler_MSSQL(DBHandlerAbstract): # FUNCTIONAL CLASS ---
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self._check_host()
...stuff and things...
gethandler.py
class test(object):
def __init__(self):
app_name = 'dbhandler_test'
logfile = 'system'
log_level = 10
screendump = True
DBO = DBHandler.handler('mssql')
...stuff and things...
Let's approach that design issue by excluding alternatives:
_check_host
implementation mixin-style, the concrete DBHandler_XXXX not fulfill their very own ctors requirements, thus being implicitly abstract themselves. So would have valid conrete product instances, but not valid product classes, which would not just be bad to maintain also water down the factory pattern.It's obvious that your design is superior to those contortionisms.
What you could however consider
is calling _check_host
in the abstract base classes' ctor and call that ctor explicitly from the DBHandler_XXXX at the appropriate point.