工厂 class 特定通用函数的适当位置(抽象 class?)
Appropriate place for factory class specific generic functions (abstract class?)
我还没有在 Stack Overflow 上找到这个特定问题的答案,所以我把它贴在这里。
我有一个工厂 class,它根据您需要的数据库(参见代码)从抽象 class 生成数据库处理对象。
我的问题是这样的;我有一些仅适用于数据库处理程序的通用方法...所以我认为将它们放入它们自己的模块中是不合适的...但我不确定将它们放在哪里合适。
将它们放在摘要中 class 当然可行,但我不知道那是否是他们接受的地方。
摘要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'
工厂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.')
功能正常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...
让我们通过排除备选方案来解决设计问题:
- 如果您不在抽象基类中实现公共保护函数 class 您将不得不在具体后代中重复其实现,这将违反 DRY 原则
- 如果你想让协变处理程序()工厂的产品聚合
_check_host
实现 mixin 风格,具体 DBHandler_XXXX 不满足他们自己的 ctors 要求,因此隐含地抽象自己。因此会有有效的具体产品实例,但不是有效的产品 classes,这不仅不利于维护,还会淡化工厂模式。
很明显你的设计比那些扭曲的要好。
你可以考虑什么
- 如果这对所有 DBHandler_XXXX 后代都可行 (!) -
在抽象基础 classes 的构造函数中调用 _check_host
,并在适当的点从 DBHandler_XXXX 显式调用该构造函数。
我还没有在 Stack Overflow 上找到这个特定问题的答案,所以我把它贴在这里。
我有一个工厂 class,它根据您需要的数据库(参见代码)从抽象 class 生成数据库处理对象。
我的问题是这样的;我有一些仅适用于数据库处理程序的通用方法...所以我认为将它们放入它们自己的模块中是不合适的...但我不确定将它们放在哪里合适。
将它们放在摘要中 class 当然可行,但我不知道那是否是他们接受的地方。
摘要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'
工厂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.')
功能正常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...
让我们通过排除备选方案来解决设计问题:
- 如果您不在抽象基类中实现公共保护函数 class 您将不得不在具体后代中重复其实现,这将违反 DRY 原则
- 如果你想让协变处理程序()工厂的产品聚合
_check_host
实现 mixin 风格,具体 DBHandler_XXXX 不满足他们自己的 ctors 要求,因此隐含地抽象自己。因此会有有效的具体产品实例,但不是有效的产品 classes,这不仅不利于维护,还会淡化工厂模式。
很明显你的设计比那些扭曲的要好。
你可以考虑什么
- 如果这对所有 DBHandler_XXXX 后代都可行 (!) -
在抽象基础 classes 的构造函数中调用 _check_host
,并在适当的点从 DBHandler_XXXX 显式调用该构造函数。