如何将此过程代码设计为基于类(面向对象)?

时间:2015-10-01 10:53:02

标签: python oop class-design

我是初学者 - 中级自学Python开发人员,

在我完成的大部分项目中,我可以看到以下程序重复。我没有任何外部家庭代码经验,我认为下面的代码不是那么专业,因为它不可重用,似乎它不适合容器中的所有东西,而是在不同模块上松散耦合的函数。

def get_query():
    # returns the query string
    pass

def make_request(query):
    # makes and returns the request with query
    pass

def make_api_call(request):
    # calls the api and returns response
    pass

def process_response(response):
    # process the response and returns the details
    pass

def populate_database(details):
    # populates the database with the details and returns the status of population
    pass

def log_status(status):
    # logs the status so that developer knows whats happening
    pass

query = get_query()
request = make_request(query)
response = make_api_call(request)
details = process_response(response)
status = populate_database(details)
log_status(status)

如何将此过程设计为基于类的设计?

3 个答案:

答案 0 :(得分:5)

如果我理解正确,您希望重用这些功能组。对此的好方法是使用这些方法创建Abstract基类,如下所示:

from abc import ABCMeta

class Generic(object):
__metaclass__  = ABCMeta


    def get_query(self):
        # returns the query string
        pass

    def make_request(self, query):
        # makes and returns the request with query
        pass

    def make_api_call(self, request):
        # calls the api and returns response
        pass

    def process_response(self, response):
        # process the response and returns the details
        pass

    def populate_database(self, details):
        # populates the database with the details and returns the status of population
        pass

    def log_status(self, status):
        # logs the status so that developer knows whats happening
        pass

现在,只要您需要在项目中使用这些方法,就可以从这个抽象类继承您的类。

class SampleUsage(Generic):

    def process_data(self):
        # In any of your methods you can call these generic functions
        self.get_query()

然后你可以创建对象来实际获得你想要的结果。

obj = SampleUsage()
obj.process_data()

答案 1 :(得分:3)

您还可以使用类名保存Python文件,或者可以使用某些功能创建外部模块,根据它们的作用将它们组织到模块中。有些模块只包含一个功能;其他人将包含很多

答案 2 :(得分:3)

我认为你的问题缺乏的是目的感。你没有理由不将完美的程序代码切换到面向对象的代码。根据原因,有几种方法可以做到这一点。由于这个问题非常常见,因此有一些常见的技术可以解决这些问题。

因此,我们假设您将主过程封装在一个对象中。你有什么需求?

  • 允许重复使用该程序,可能会覆盖某些部分?请参阅下面的模板方法模式。
  • 允许在运行时根据外部因素动态改变过程的行为?查看Strategy模式。
  • 允许在运行时根据内部因素动态更改过程的行为?例如,如果某个请求可能会将程序切换到"维护模式"?查看State模式。

我只是描述模板方法模式,它看起来最接近Marty的顾虑。 我将示例缩减为3个步骤,以便更容易解释,但我为您制作了fully working example gist

template method

您想提供一种重用程序的方法,同时允许覆盖一些明确定义的部分吗?让我们创建一个空的,填空的模板:

class BaseRequestProcesor(object):
    def get_query(self):
        raise NotImplementedError()

    def process_query(self, query):
        raise NotImplementedError()

    def log_status(self, status):
        raise NotImplementedError()

    def process(self): # main procedure
        query = self.get_query()
        status = self.process_query(query)
        self.log_status(status)

    __call__ = process # allow "calling" the requestprocessor

我们有基本模板。让我们创建一些模板填充程序:

class DemoQueryReader(object):
    def get_query(self):
        return 'this is a query'

class HelloQueryProcessor(object):
    def process_query(self, query):
        return 'Hello World, {}!'.format(query)

class StdoutLogProcessor(object):
    def log_status(self, status):
        print(status)

现在从我们想要的位构建一个完整的请求处理器。这是作品汇集在一起​​的地方:

class DemonstrationProcessor(DemonQueryReader, HelloQueryProcessor, StdoutLogProcessor, BaseRequestProcessor):
    pass

在控制台中演示:

>>> from marty_example import DemonstrationProcessor
>>> processor = DemonstrationProcessor()
>>> processor()
Hello World, this is a query!

这是你可以建立的最迂腐的例子。你可以在有意义的时候提供默认实现(大部分都不做)。如果有意义的话,你可以组合起来。

关键是,您将流程设置为模板,允许轻松覆盖所选的详细信息,同时仍然可以控制整个工作流程。这是inversion of control的一种形式。