我在Python 3.1中编写了一个URL路由器,并想知道使用以下变体之一是否不仅仅是品味问题:
元组作为构造函数参数:
router = Router(
(r"/item/{id}", ItemResource()),
(r"/article/{title}", ArticleResource())
)
方法调用
router = Router()
router.connect(r"/item/{id}", ItemResource())
router.connect(r"/article/{title}", ArticleResource())
你认为这有什么优点或缺点吗?
答案 0 :(得分:2)
传统的OOP视图是构造函数应该保证对象处于最终的可用状态 - 也就是说,当有动态变化的需求时,状态可能会改变(例如,有{{1} }}方法与disconnect
一起使用,以及实际的应用程序要求,以便在操作过程中动态更改路由?),但它“应该”从对象诞生的那一刻起,到“它消失了。
在现实世界中,替代模式有时被称为“两阶段构造”(虽然这里可能不仅仅是两个阶段,因为你一直在调用connect
;-)在灵活性方面可能有一些优势 - 持久化和解除持久化对象,依赖于配置文件构建它们,简化依赖注入和模拟(以及测试)。
你是否真的 利用这些灵活性方面,这是一个你可以比我们更好地回答的问题...因为你最了解你的应用程序的确切要求和你自己的技能面向对象开发,测试和优先考虑的偏好。如果你不,事实上,要使用灵活性方面,那么完全省略它们就更简单了,并采用“传统的自给自足的构造函数”OOP方法。
答案 1 :(得分:2)
我赞成将元组传递给构造函数,原因有两点,Alex没有提及(至少没有明确说明)。
可读性。如果代码的任何读者都明白,路由器实例需要一个可用的路由列表。
失去耦合。客户端代码不必为初始化Router实例而烦恼。这是Router类的责任。
如果这对你来说太笨重,我建议将Router类分成更小的类,并将这些类的实例传递给Router.__init__
。例如,您可以在此处使用RoutesList
类:
routes = RoutesList((r"/item/{id}", ItemResource()),
(r"/article/{title}", ArticleResource()))
router = Router(routes)
这为您提供了Alex提到的两阶段构造的灵活性,但也阻止了客户端代码对初始化路由器类负责。这仍然保留了可读性,因为您必须向后阅读以查看routes
是什么而不是前进(如果您不记得的话)。它还有一个额外的好处,如果你决定改变你的路由表示方式,那么Router类就不应该改变了:所有这些改变都应该封装在RoutesList类中(或者甚至可以在undefined Route class)。
或者路由可以只是一个元组列表,你可以有一个模块级函数来将路由映射到控制器;)
答案 2 :(得分:0)
除非参数是强制性的,否则您可以使用方法调用方法,如果您将来需要添加更多内容,则会更灵活。
如果必须使用两个参数才能使实例有效,请使用构造函数方法。
答案 3 :(得分:0)
由于您正在构建路由器以将Web请求路由到适当的资源,因此您还可以查看路由。它允许您将URL映射到应用程序的操作。