Python中的工厂方法

and*_*tti 5 python

我正在处理以下小项目:https : //github.com/AndreaCrotti/project-organizer

简而言之,它旨在更轻松地管理许多不同的项目。有用的事情之一是一种自动检测我正在处理的项目类型,正确设置一些命令的方法。

目前,我正在使用类方法“匹配”功能和一个对各种“匹配”进行迭代的检测功能。我敢肯定可能会有更好的设计,但是找不到。

有任何想法吗?

class ProjectType(object):
    build_cmd = ""

    @classmethod
    def match(cls, _):
        return True


class PythonProject(ProjectType):
    build_cmd = "python setup.py develop --user"

    @classmethod
    def match(cls, base):
        return path.isfile(path.join(base, 'setup.py'))


class AutoconfProject(ProjectType):
    #TODO: there should be also a way to configure it
    build_cmd = "./configure && make -j3"

    @classmethod
    def match(cls, base):
        markers = ('configure.in', 'configure.ac', 'makefile.am')
        return any(path.isfile(path.join(base, x)) for x in markers)


class MakefileOnly(ProjectType):
    build_cmd = "make"

    @classmethod
    def match(cls, base):
        # if we can count on the order the first check is not useful
        return (not AutoconfProject.match(base)) and \
            (path.isfile(path.join(base, 'Makefile')))


def detect_project_type(path):
    prj_types = (PythonProject, AutoconfProject, MakefileOnly, ProjectType)
    for p in prj_types:
        if p.match(path):
            return p()
Run Code Online (Sandbox Code Playgroud)

Ray*_*ger 5

这是对工厂函数作为类方法的合理使用。

一种可能的改进是让所有类都从单个父类继承,该父类将具有一个将所有逻辑都合并到detect_project_type中的类方法

也许这样的事情会起作用:

class ProjectType(object):
    build_cmd = ""
    markers = []

    @classmethod
    def make_project(cls, path):
        prj_types = (PythonProject, AutoconfProject, MakefileOnly, ProjectType)
        for p in prj_types:
            markers = p.markers
            if any(path.isfile(path.join(path, x)) for x in markers):
                return p()

class PythonProject(ProjectType):
    build_cmd = "python setup.py develop --user"
    markers = ['setup.py']

class AutoconfProject(ProjectType):
    #TODO: there should be also a way to configure it
    build_cmd = "./configure && make -j3"
    markers = ['configure.in', 'configure.ac', 'makefile.am']

class MakefileOnly(ProjectType):
    build_cmd = "make"
    markers = ['Makefile']
Run Code Online (Sandbox Code Playgroud)