我对Twisted web框架非常感兴趣。据我所知的框架 使用好莱坞原则。我只知道这个词,但完全没有 关于这种设计模式的想法。 我已经做了很多谷歌搜索的实施 Python中的好莱坞原则。但结果很少。 有没有人能给我看一些简单的python代码来描述这种设计模式?
答案 0 :(得分:6)
我以前从未听过“好莱坞原则”这个词,也不熟悉Twisted(虽然我觉得我应该这样)。但控制反转的概念并不那么困难。我认为GUI编程是介绍它的好方法。请考虑here中的以下内容(稍加修改)。
import Tkinter
class App(object):
def __init__(self, master):
frame = Tkinter.Frame(master)
frame.pack()
self.button = Tkinter.Button(frame, text="QUIT", fg="red", command=frame.quit)
self.button.pack(side=Tkinter.LEFT)
self.hi_there = Tkinter.Button(frame, text="Hello", command=self.say_hi)
self.hi_there.pack(side=Tkinter.LEFT)
def say_hi(self):
print "hi there, everyone!"
root = Tkinter.Tk()
app = App(root)
root.mainloop()
这是控制反转的一个非常简单的例子。它使用回调 - 因此Hollywood principle名字对象(感谢Sven的链接)。这个想法是你写了一个函数,但你从来没有调用它。相反,你把它交给另一个程序并告诉该程序何时调用它。然后你控制该程序。以下是代码的详细说明:
import Tkinter
class App(object):
我们从一个类定义开始,它将保存我们的回调并将它们传递给我称之为“主程序”的相应部分。
def __init__(self, master):
我们班需要一个“硕士课程”;主程序将调用我们定义的函数。在这种情况下,它是GUI的根窗口。更准确地说,在GUI编程的上下文中,我们可能会说master
是frame
的父。
frame = Tkinter.Frame(master)
frame.pack()
这两行创建了一个Frame
对象,它本质上是一个包含小部件的框。你会在一秒钟内看到一个小部件。正如您所看到的,它还有一个父级 - 与我们App
的父级相同:master
。
self.button = Tkinter.Button(frame, text="QUIT", command=frame.quit)
self.button.pack(side=Tkinter.LEFT)
self.button
是一个小部件。使用Tkinter.Button
创建它时,会为其提供一些属性,例如标签(text="QUIT"
)。你还告诉它它的父亲是什么 - 在这种情况下,不是master
,而是frame
。所以现在我们有了一个层次结构 - master -> frame -> button
。但我们最重要的是:command=frame.quit
。这告诉按钮通过鼠标单击激活时该怎么做。简而言之,这就是回调。在这里,我们传递frame
的{{1}}方法,在这种情况下导致整个程序退出。请注意,该功能后面没有quit
- 这是因为不想要调用它。我们只想将其交给()
。
button
这是另一个与第一个小部件几乎相同的小部件,唯一的例外是我们已经通过 self.hi_there = Tkinter.Button(frame, text="Hello", command=self.say_hi)
self.hi_there.pack(side=Tkinter.LEFT)
而不是将self.quit
作为回调传递。由于这是在下面定义的,您可以替换您想要的任何功能。 (在上述两个行中,self.say_hi
只是告诉self.button.pack
它应该在Button
中的位置。)
frame
def say_hi(self):
print "hi there, everyone!"
用于定义say_hi
按钮的功能。
Hello
现在我们调用我们的类,创建一个实例。我们创建根窗口,然后创建一个root = Tkinter.Tk()
app = App(root)
实例,其中App
为其父级。
root
然后我们完成了。我们将控制传递给Tkinter,后者完成剩下的工作。
答案 1 :(得分:2)
Twisted是采用异步方法设计的。你的程序会导致某些事情发生,但它不会等待那件事发生,而是将控制权传递给扭曲的事件循环(扭曲的说法中的'reactor')。当反应堆发现某些东西需要你注意时,它将使用你最初调用该动作时提供的“回调”来调用你的程序。基本工作流程如下所示。首先,
something_deferred = make.twisted.do.something()
something_deferred
通常是twisted.internet.defer.Deferred
个实例,代表something()
的结果。通常,something()
需要一些时间才能完成,因此即使something()
立即返回,延迟对象也没有结果。那么你需要做的是定义一个函数,一旦结果准备好就可以调用twisted。
def something_callback(result):
do_something_else(result)
在大多数情况下,您还应该定义一个函数来处理something()
中发生错误的情况,
def something_errback(fault):
cleanup_something()
最后,当something()
最终准备好时,你必须告诉你想让它使用这些功能。
something_deferred.addCallbacks(something_callback, something_errback)
请注意,您不会自行调用这些函数,只需将其名称传递给addCallbacks()
即可。 Twisted本身负责调用你的函数。
并非每个示例都遵循此确切模式,但在大多数情况下,您将实例方法放在实现扭曲定义接口的类中,或者将可调用函数传递给生成事件的扭曲函数。
答案 2 :(得分:2)
“好莱坞原则”之所以如此命名,是因为在好莱坞的电影界,紧张的第一次演员有时会在试镜后一遍又一遍地打电话给工作室,看他们是否得到了这个部分。在软件开发中,我们称之为polling,而且效率极低。在好莱坞的比喻中,它甚至浪费了成功的申请人的时间(因为他们可能在选择之前反复调用)并且浪费了工作室的时间(因为许多未被选中的应用程序仍会称之为)。
这是一个Python文件,希望能够阐明实际的原则:
首先,我们有一个Actor
,可以为试镜表演或获得一部分:
class Actor(object):
def __init__(self, name):
self.name = name
def youGotThePart(self):
print self.name, "got the part."
def perform(self):
print self.name, "performs an audition."
然后,我们有铸造过程:
applicants = []
def audition(actor):
actor.perform()
applicants.append(actor)
def cast():
import random
selection = random.choice(applicants)
selection.youGotThePart()
试镜要求演员表演,当演员发生时,选择演员(随机 - 作为好莱坞演员的非参与者,我怀疑这可能是最真实的模拟)。那个演员然后得到通知(工作室“称他们”)。
最后,这是整个铸造过程:
alice = Actor("alice")
bob = Actor("bob")
carol = Actor("carol")
dave = Actor("dave")
audition(alice)
audition(bob)
audition(carol)
audition(dave)
cast()
如您所见,这非常简单,不涉及GUI或网络或任何其他外部输入源。它只是构建代码的一种方法,以避免浪费检查和重新检查相同的状态。如果您考虑将此程序构造为 not ,请遵循相关原则,您将得到如下循环:
while True:
for actor in alice, bob, carol, dave:
if actor.didIGetThePart():
break
maybeGiveSomeoneThePart()
这当然是非常浪费的,因为谁知道演员在工作室选择之前可以拨打多少次电话?