{"id":708,"date":"2023-11-26T14:12:47","date_gmt":"2023-11-26T06:12:47","guid":{"rendered":"http:\/\/ai.gitpp.com\/?p=708"},"modified":"2023-11-26T14:12:47","modified_gmt":"2023-11-26T06:12:47","slug":"%e4%b8%80%e4%b8%aa%e5%ae%9e%e7%94%a8%e7%9a%84%e5%9f%ba%e4%ba%8epython%e7%9a%84%e5%ae%9e%e7%8e%b0%e5%90%84%e7%a7%8d%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f%e7%9a%84%e9%80%9a%e7%94%a8%e4%bb%a3%e7%a0%81","status":"publish","type":"post","link":"http:\/\/ai.gitpp.com\/index.php\/2023\/11\/26\/%e4%b8%80%e4%b8%aa%e5%ae%9e%e7%94%a8%e7%9a%84%e5%9f%ba%e4%ba%8epython%e7%9a%84%e5%ae%9e%e7%8e%b0%e5%90%84%e7%a7%8d%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f%e7%9a%84%e9%80%9a%e7%94%a8%e4%bb%a3%e7%a0%81\/","title":{"rendered":"\u4e00\u4e2a\u5b9e\u7528\u7684\u57fa\u4e8epython\u7684\u5b9e\u73b0\u5404\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u7684\u901a\u7528\u4ee3\u7801\u5e93"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>PyPattyrn \u662f\u4e00\u4e2a\u5b9e\u7528\u7684 Python \u5305\uff0c\u5b83\u6c47\u96c6\u4e86\u5404\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u7684\u901a\u7528\u4ee3\u7801\uff0c\u4ee5\u4fbf\u4e8e\u5f00\u53d1\u8005\u4eec\u5728\u81ea\u5df1\u7684\u9879\u76ee\u4e2d\u8f7b\u677e\u3001\u5feb\u901f\u5730\u5e94\u7528\u8fd9\u4e9b\u6a21\u5f0f\u3002\u8bbe\u8ba1\u6a21\u5f0f\u662f\u89e3\u51b3\u7279\u5b9a\u95ee\u9898\u7684\u7ecf\u9a8c\u8bc1\u7684\u65b9\u6cd5\uff0c\u867d\u7136\u4e0d\u80fd\u76f4\u63a5\u8f6c\u6362\u4e3a\u4ee3\u7801\uff0c\u4f46\u5b83\u4eec\u7684\u5b9e\u73b0\u5f80\u5f80\u5177\u6709\u5f88\u591a\u5171\u6027\u3002<\/p>\n\n\n\n<p>\u901a\u8fc7\u4f7f\u7528 PyPattyrn \u5305\uff0c\u60a8\u53ef\u4ee5\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u51cf\u5c11\u91cd\u590d\u4ee3\u7801\uff1a\u4e0d\u5fc5\u5728\u6bcf\u4e2a\u9879\u76ee\u4e2d\u4ece\u5934\u7f16\u5199\u901a\u7528\u4ee3\u7801\uff0cPyPattyrn \u5df2\u7ecf\u4e3a\u60a8\u51c6\u5907\u597d\u4e86\u3002<\/li>\n\n\n\n<li>\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff1a\u5229\u7528\u5df2\u9a8c\u8bc1\u7684\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u4f7f\u60a8\u7684\u9879\u76ee\u66f4\u52a0\u6a21\u5757\u5316\u3001\u53ef\u7ef4\u62a4\u548c\u53ef\u6269\u5c55\u3002<\/li>\n\n\n\n<li>\u5b66\u4e60\u8bbe\u8ba1\u6a21\u5f0f\uff1aPyPattyrn \u63d0\u4f9b\u7684\u4ee3\u7801\u793a\u4f8b\u53ef\u4ee5\u5e2e\u52a9\u60a8\u66f4\u597d\u5730\u7406\u89e3\u8bbe\u8ba1\u6a21\u5f0f\u7684\u5de5\u4f5c\u539f\u7406\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u8981\u5728\u9879\u76ee\u4e2d\u4f7f\u7528 PyPattyrn\uff0c\u8bf7\u9075\u5faa\u4ee5\u4e0b\u6b65\u9aa4\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u5b89\u88c5 PyPattyrn\uff1a\u4f7f\u7528 pip \u547d\u4ee4\u5b89\u88c5 PyPattyrn \u5305\uff1a<code>pip install PyPattyrn<\/code>\u3002<\/li>\n\n\n\n<li>\u5bfc\u5165\u6240\u9700\u7684\u6a21\u5757\uff1a\u5728 Python \u4ee3\u7801\u4e2d\uff0c\u5bfc\u5165\u76f8\u5e94\u7684\u6a21\u5757\u4ee5\u4f7f\u7528 PyPattyrn \u63d0\u4f9b\u7684\u7c7b\u548c\u51fd\u6570\u3002<\/li>\n\n\n\n<li>\u4f7f\u7528 PyPattyrn \u4ee3\u7801\uff1a\u6839\u636e\u9700\u8981\u8c03\u7528 PyPattyrn \u63d0\u4f9b\u7684\u7c7b\u548c\u51fd\u6570\uff0c\u6765\u5b9e\u73b0\u8bbe\u8ba1\u6a21\u5f0f\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u867d\u7136 PyPattyrn \u63d0\u4f9b\u4e86\u5927\u91cf\u8bbe\u8ba1\u6a21\u5f0f\u7684\u901a\u7528\u4ee3\u7801\uff0c\u4f46\u5e76\u4e0d\u610f\u5473\u7740\u60a8\u5e94\u8be5\u5728\u6240\u6709\u60c5\u51b5\u4e0b\u90fd\u4f7f\u7528\u5b83\u4eec\u3002\u9879\u76ee\u7684\u5177\u4f53\u9700\u6c42\u548c\u573a\u666f\u53ef\u80fd\u9700\u8981\u60a8\u6839\u636e\u5b9e\u9645\u60c5\u51b5\u8fdb\u884c\u8c03\u6574\u548c\u4f18\u5316\u3002<\/p>\n\n\n\n<p>\u603b\u4e4b\uff0cPyPattyrn \u662f\u4e00\u4e2a\u5b9d\u8d35\u7684\u8d44\u6e90\uff0c\u5b83\u53ef\u4ee5\u5e2e\u52a9\u60a8\u66f4\u9ad8\u6548\u5730\u5c06\u8bbe\u8ba1\u6a21\u5f0f\u5e94\u7528\u5230 Python \u9879\u76ee\u4e2d\u3002\u901a\u8fc7\u51cf\u5c11\u91cd\u590d\u4ee3\u7801\u3001\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\u4ee5\u53ca\u5b66\u4e60\u6700\u4f73\u5b9e\u8df5\uff0c\u60a8\u53ef\u4ee5\u66f4\u597d\u5730\u6784\u5efa\u9ad8\u8d28\u91cf\u3001\u53ef\u6269\u5c55\u7684\u8f6f\u4ef6\u7cfb\u7edf\u3002<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u5b89\u88c5<\/h3>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install pypattyrn\n<\/code><\/pre>\n\n\n\n<p>\u6216\u8005<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/tylerlaberge\/PyPattyrn.git\ncd PyPattyrn\npython setup.py install\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#examples\"><\/a>\u4f8b\u5b50<\/h3>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#behavioral-patterns\"><\/a>\u884c\u4e3a\u6a21\u5f0f<\/h4>\n\n\n\n<p>\u5904\u7406\u5bf9\u8c61\u4e4b\u95f4\u901a\u4fe1\u7684\u6a21\u5f0f\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#chain-of-responsibility-pattern\"><\/a>\u8d23\u4efb\u94fe\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u6cbf\u7740\u5bf9\u8c61\u94fe\u4f20\u9012\u8bf7\u6c42\uff0c\u76f4\u5230\u8bf7\u6c42\u88ab\u5904\u7406\u3002from pypattyrn.behavioral.chain import Chain, ChainLink class ConcreteChainLinkThree(ChainLink): # This object is a ChainLink def handle(self, request): # Implement the handle method. if request == &#8216;handle_three&#8217;: return &#8220;Handled in chain link three&#8221; else: return self.successor_handle(request) # If this ChainLink can&#8217;t handle the request, # ask its successor to handle it. # (Has no successor so will raise AttributeError) # (This exception is caught and will call a Chains fail method) class ConcreteChainLinkTwo(ChainLink): # This object is a ChainLink def __init__(self): # Override init to set a successor on initialization. super().__init__() # first call ChainLinks init self.set_successor(ConcreteChainLinkThree()) # Set the successor of this chain link # to a ConcreteChainLinkThree instance. def handle(self, request): # Implement the handle method. if request == &#8216;handle_two&#8217;: return &#8220;Handled in chain link two&#8221; else: return self.successor_handle(request) # If this ChainLink can&#8217;t handle a request # ask its successor to handle it # (the ConcreteChainLinkThree instance). class ConcreteChainLinkOne(ChainLink): # This object is a ChainLink def __init__(self): super().__init__() self.set_successor(ConcreteChainLinkTwo()) # Set the successor of this ChainLink # to a ConcreteChainLinkTwo instance. def handle(self, request): # Implement the handle method. if request == &#8216;handle_one&#8217;: return &#8220;Handled in chain link one&#8221; else: return self.successor_handle(request) # If this ChainLink can&#8217;t handle a request # ask its successor to handle it # (the ConcreteChainLinkTwo instance). class ConcreteChain(Chain): # This object is a Chain def __init__(self): # Override init to initialize a Chain with the starting chain link. super().__init__(ConcreteChainLinkOne()) # Initialize this Chain with a start chain link. # (a ConcreteChainLinkOne instance) def fail(self): # Implement the fail method, this is called if no chain links could handle a request. return &#8216;Fail&#8217; chain = ConcreteChain() assert &#8220;Handled in chain link one&#8221; == chain.handle(&#8220;handle_one&#8221;) assert &#8220;Handled in chain link two&#8221; == chain.handle(&#8220;handle_two&#8221;) assert &#8220;Handled in chain link three&#8221; == chain.handle(&#8220;handle_three&#8221;) assert &#8220;Fail&#8221; == chain.handle(&#8216;handle_four&#8217;)<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#command-pattern\"><\/a>\u547d\u4ee4\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u5c06\u7528\u4e8e\u6267\u884c\u64cd\u4f5c\u7684\u4fe1\u606f\u5c01\u88c5\u5230\u5bf9\u8c61\u4e2d\u3002from pypattyrn.behavioral.command import Receiver, Command, Invoker class Thermostat(Receiver): # This object is a Receiver. # Contains methods for commands to use. def raise_temp(self, amount): return &#8220;Temperature raised by {0} degrees&#8221;.format(amount) def lower_temp(self, amount): return &#8220;Temperature lowered by {0} degrees&#8221;.format(amount) class RaiseTempCommand(Command): # This object is a Command. def __init__(self, receiver, amount=5): # Override init to include a temperature amount argument. super().__init__(receiver) self.amount = amount def execute(self): # Implement the execute method. return self._receiver.action(&#8216;raise_temp&#8217;, self.amount) # Call on the Receiver&#8217;s action method with # the name of the method to call and args. # (Raises the temperature by 5 degrees.) def unexecute(self): # Implement the unexecute method. return self._receiver.action(&#8216;lower_temp&#8217;, self.amount) # Calls on the Receiver to lower # the temperature by 5 degrees. class LowerTempCommand(Command): # This object is a Command. def __init__(self, receiver, amount=5): super().__init__(receiver) self.amount = amount def execute(self): return self._receiver.action(&#8216;lower_temp&#8217;, self.amount) # Call on the receiver to lower the # temperature by 5 degrees. def unexecute(self): return self._receiver.action(&#8216;raise_temp&#8217;, self.amount) # Call on the receiver to raise the # temperature by 5 degrees. class Worker(Invoker): # This object is the Invoker def __init__(self): # Override init to initialize an Invoker with Commands to accept. super().__init__([LowerTempCommand, RaiseTempCommand]) # Initialize the Invoker with the # LowerTempCommand and RaiseTempCommand classes. thermostat = Thermostat() # Create a Receiver. worker = Worker() # Create an Invoker. assert &#8220;Temperature lowered by 5 degrees&#8221; == worker.execute(LowerTempCommand(thermostat)) # Have the Invoker execute a LowerTempCommand # which uses the thermostat Receiver. assert &#8220;Temperature raised by 5 degrees&#8221; == worker.execute(RaiseTempCommand(thermostat)) # Have the Invoker execute a RaiseTempCommand # which uses the thermostat Receiver. assert &#8220;Temperature lowered by 5 degrees&#8221; == worker.undo() # Undo the previous command (Calls the RaiseTempCommand unexecute method.)<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#iterator-pattern\"><\/a>\u8fed\u4ee3\u5668\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u4e00\u79cd\u987a\u5e8f\u8bbf\u95ee\u96c6\u5408\u4e2d\u5143\u7d20\u7684\u65b9\u6cd5\u3002from pypattyrn.behavioral.iterator import Iterable, Iterator class Counter(Iterable): # This object is an Iterable def __init__(self, max): self.count = 0 self.max = max def __next__(self): # Implement the __next__ method. self.count += 1 # Increment the count if self.count &gt; self.max: raise StopIteration() # make sure to raise StopIteration at the appropriate time. else: return self.count &#8211; 1 # Return the count class CounterIterator(Iterator): # This object is an Iterator def __init__(self): # Override init to initialize an Iterator with the Counter object. super().__init__(Counter(10)) # Initialize the iterator with a Counter that goes to 10. counter_iterator = CounterIterator() # Create a CounterIterator. for count in counter_iterator: # You can loop through it how you would expect. print(count) # 0, 1, 2, 3, &#8230;, 9<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#mediator-pattern\"><\/a>\u4e2d\u4ecb\u8005\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u7528\u4e8e\u7ba1\u7406\u8bb8\u591a\u5bf9\u8c61\u4e4b\u95f4\u901a\u4fe1\u7684\u4e2d\u4ecb\u3002from pypattyrn.behavioral.mediator import Mediator class Dog(object): sound = &#8221; def set_sound(self, sound): self.sound = sound class Cat(object): sound = &#8221; def set_sound(self, sound): self.sound = sound dog = Dog() cat = Cat() mediator = Mediator() # Create a Mediator object. mediator.connect(&#8216;set_dog_sound&#8217;, dog.set_sound) # Connect the signal &#8216;set_dog_sound&#8217; to the dog.set_sound method. mediator.connect(&#8216;set_cat_sound&#8217;, cat.set_sound) # Connect the signal &#8216;set_cat_sound&#8217; to the cat.set_sound method. mediator.connect(&#8216;set_sound&#8217;, dog.set_sound) # Also connect the signal &#8216;set_sound&#8217; to the dog.set_sound method. mediator.connect(&#8216;set_sound&#8217;, cat.set_sound) # Also connect the signal &#8216;set_sound&#8217; to the cat.set_sound method. mediator.signal(&#8216;set_sound&#8217;, &#8216;foo&#8217;) # Send out the signal &#8216;set_sound&#8217; # with an argument to be passed to the connected methods. # (Sets dog.sound and cat.sound to &#8216;foo&#8217;) assert &#8216;foo&#8217; == dog.sound assert &#8216;foo&#8217; == cat.sound mediator.signal(&#8216;set_dog_sound&#8217;, &#8216;woof&#8217;) # Send out the signal &#8216;set_dog_sound&#8217; # (Sets dog.sound to &#8216;woof&#8217;) mediator.signal(&#8216;set_cat_sound&#8217;, &#8216;meow&#8217;) # Send out the signal &#8216;set_cat_sound&#8217; # (Sets cat.sound to &#8216;meow&#8217;) assert &#8216;woof&#8217; == dog.sound assert &#8216;meow&#8217; == cat.sound mediator.disconnect(&#8216;set_sound&#8217;, dog.set_sound) # Disconnect the method dog.sound from the signal &#8216;set_sound&#8217; mediator.signal(&#8216;set_sound&#8217;, &#8216;bar&#8217;) # Send out the signal &#8216;set_sound&#8217; # (Only sets cat.sound to &#8216;bar&#8217; because we disconnected dog.sound) assert &#8216;woof&#8217; == dog.sound assert &#8216;bar&#8217; == cat.sound<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#memento-pattern\"><\/a>\u7eaa\u5ff5\u54c1\u56fe\u6848<\/h5>\n\n\n\n<p>\u4fdd\u5b58\u5bf9\u8c61\u7684\u72b6\u6001\u5e76\u5728\u7a0d\u540e\u56de\u6eda\u5230\u8be5\u72b6\u6001\u3002from pypattyrn.behavioral.memento import Originator class Cat(Originator): # This object is an Originator def __init__(self, name): self.name = name cat = Cat(&#8216;Tom&#8217;) # Initialize a Cat with the name &#8216;Tom&#8217; assert cat.name == &#8216;Tom&#8217; cat_memento = cat.commit() # Save the cats current state to a Memento object. cat.name = &#8216;jerry&#8217; # Change the cats name to &#8216;jerry&#8217; assert cat.name == &#8216;jerry&#8217; cat.rollback(cat_memento) # Restore the cats state to the memento object we saved. assert &#8216;Tom&#8217; == cat.name # The cats name was changed back to &#8216;Tom&#8217; as expected.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#null-object-pattern\"><\/a>\u7a7a\u5bf9\u8c61\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u5c06\u4e0d\u5b58\u5728\u7684\u5bf9\u8c61\u5c01\u88c5\u4e3a\u5177\u6709\u4e2d\u6027\u884c\u4e3a\u7684\u5bf9\u8c61\u3002from pypattyrn.behavioral.null import Null # You can initialize a Null object with any parameters. try: Null() Null(&#8216;value&#8217;) Null(&#8216;value&#8217;, param=&#8217;value&#8217;) except: raise AssertionError() null = Null() # Attempting to set parameters won&#8217;t do anything and won&#8217;t error try: null.foo = &#8216;foo&#8217; null.foo.bar = &#8216;bar&#8217; except: raise AssertionError() # Calling on a null object in any way will just return that null object. assert null == null() assert null == null(&#8216;value&#8217;) assert null == null(&#8216;value&#8217;, param=&#8217;value&#8217;) assert null == null.foo assert null == null.foo.bar assert null == null.foo.bar.method1() assert null == null.foo.bar.method1().method2(&#8216;foo&#8217;, bar=&#8217;bar&#8217;).attr3 assert str(null) == &#8221; # Null objects string representation is the empty string. assert repr(null) == &#8221; # Null objects repr is the empty string. assert bool(null) is False # Null object evaluates to False as a boolean. # Trying to delete attributes doesn&#8217;t do anything and won&#8217;t error. try: del null.foo del null.foo.bar except: raise AssertionError()<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#observer-pattern\"><\/a>\u89c2\u5bdf\u8005\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u5f53\u5355\u4e2a\u5bf9\u8c61\u7684\u72b6\u6001\u53d1\u751f\u53d8\u5316\u65f6\u901a\u77e5\u8bb8\u591a\u5bf9\u8c61\u3002from pypattyrn.behavioral.observer import Observable, Observer class ConcreteObservable(Observable): # This object is an Observable. _kinda_private_var = &#8216;I am kinda private&#8217; __private_var = &#8216;I am more private&#8217; def change_state(self, **kwargs): # Some method to change this objects state and notify observers. for key, value in kwargs.items(): setattr(self, key, value) # Change the objects state. self.notify() # Notify all observers of the change in state. # Will call the update method of each attached observer with kwargs that come # from this objects __dict__ attribute, minus any private variables (starts with __ or _) class ConcreteObserver(Observer): # This object is an Observer. updated_state = None def update(self, **state): # Implement the update method. # Called when an attached observable calls its notify method. self.updated_state = state observable = ConcreteObservable() # Create an Observable observer_1 = ConcreteObserver() # Create Observers observer_2 = ConcreteObserver() observer_3 = ConcreteObserver() observable.attach(observer_1) # Attach each of the Observers to the Observable observable.attach(observer_2) observable.attach(observer_3) observable.change_state(foo=&#8217;foo&#8217;, bar=&#8217;bar&#8217;) # Change the Observable&#8217;s state. # Also calls notify which will call each Observers update method. expected_state = {&#8216;foo&#8217;: &#8216;foo&#8217;, &#8216;bar&#8217;: &#8216;bar&#8217;} # Make sure each Observers state was changed accordingly when the notify method was called by the Observable. assert sorted(expected_state.keys()) == sorted(observer_1.updated_state.keys()) and \\ sorted(expected_state.values()) == sorted(observer_1.updated_state.values()) assert sorted(expected_state.keys()) == sorted(observer_2.updated_state.keys()) and \\ sorted(expected_state.values()) == sorted(observer_2.updated_state.values()) assert sorted(expected_state.keys()) == sorted(observer_3.updated_state.keys()) and \\ sorted(expected_state.values()) == sorted(observer_3.updated_state.values()) observable.detach(observer_1) # Detach Observer 1 from the Observable observable.change_state(bar=&#8217;foobar&#8217;) # Change the Observables state. expected_state_2 = {&#8216;foo&#8217;: &#8216;foo&#8217;, &#8216;bar&#8217;: &#8216;foobar&#8217;} # Make sure each Observers state was changed accordingly when notify was called by the Observable, # Except for observer_1 because we detached that Observer from the Observable. assert sorted(expected_state_2.keys()) != sorted(observer_1.updated_state.keys()) or \\ sorted(expected_state_2.values()) != sorted(observer_1.updated_state.values()) assert sorted(expected_state_2.keys()) == sorted(observer_2.updated_state.keys()) and \\ sorted(expected_state_2.values()) == sorted(observer_2.updated_state.values()) assert sorted(expected_state_2.keys()) == sorted(observer_3.updated_state.keys()) and \\ sorted(expected_state_2.values()) == sorted(observer_3.updated_state.values())<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#visitor-pattern\"><\/a>\u8bbf\u5ba2\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u5411\u73b0\u6709\u7c7b\u6dfb\u52a0\u65b0\u64cd\u4f5c\u800c\u4e0d\u4fee\u6539\u5b83\u3002from pypattyrn.behavioral.visitor import Visitee, Visitor class A(Visitee): # This object is a Visitee pass class B(A): # This object is an A, which also makes this a Visitee. pass class C(B): # This object is a B, which also makes this a Visitee. pass class D(Visitee): # This object is a Visitee pass class NodeVisitor(Visitor): # This object is a Visitor def generic_visit(self, node, *args, **kwargs): # Implement the generic visit method. # This is called when there is no visit_ method # implemented for a particular visitee. return &#8216;generic_visit &#8216; + node.__class__.__name__ def visit_b(self, node, *args, **kwargs): # Called when this object visits a Visitee of class &#8216;B&#8217;. return &#8216;visit_b &#8216; + node.__class__.__name__ def visit_d(self, node, *args, **kwargs): # Called when this object visits a Visitee of class &#8216;D&#8217;. return &#8216;visit_d {0} args: {1} kwargs: {2}&#8217;.format(node.__class__.__name__, args, kwargs) # Create Visitee&#8217;s node_a = A() node_b = B() node_c = C() node_d = D() # Create Visitor node_visitor = NodeVisitor() assert &#8216;generic_visit A&#8217; == node_a.accept(node_visitor) # Visit node_a with the Visitor. # Since the visitor does not have a visit_a method, # generic_visit is called. assert &#8216;visit_b B&#8217; == node_b.accept(node_visitor) # Visit node_b with the Visitor. # Calls the visitors visit_b method. assert &#8216;visit_b C&#8217; == node_c.accept(node_visitor) # Visit node_c with the Visitor. # Even though the visitor does not have a visit_c method, # since node_c inherits B, the Visitors visit_b method is called. # Visit node_d with the Visitor. Calls the visitors visit_d method. assert &#8220;visit_d D args: (&#8216;foo&#8217;, &#8216;bar&#8217;) kwargs: {&#8216;foobar&#8217;: &#8216;foobar&#8217;}&#8221; == node_d.accept(node_visitor, &#8216;foo&#8217;, &#8216;bar&#8217;, foobar=&#8217;foobar&#8217;)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#creational-patterns\"><\/a>\u521b\u4f5c\u6a21\u5f0f<\/h4>\n\n\n\n<p>\u5904\u7406\u5bf9\u8c61\u521b\u5efa\u7684\u6a21\u5f0f\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#builder-pattern\"><\/a>\u5efa\u9020\u8005\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u5c06\u5bf9\u8c61\u6784\u9020\u4e0e\u5176\u8868\u793a\u5206\u5f00\u3002from pypattyrn.creational.builder import Builder, Director class Building(object): # The object being constructed. def __init__(self): self.floor = None self.size = None def __repr__(self): return &#8216;Floor: {0.floor} | Size: {0.size}&#8217;.format(self) class HomeBuilder(Builder): # A base Builder class for constructing homes. def __init__(self): super().__init__(Building()) # Initialize the Builder class with a Building instance. self._register(&#8216;floor&#8217;, self._build_floor) # Register the keyword &#8216;floor&#8217; with the _build_floor method. self._register(&#8216;size&#8217;, self._build_size) # Register the keyword &#8216;size&#8217; with the _build_size method. def _build_floor(self): pass def _build_size(self): pass class HouseBuilder(HomeBuilder): # A concrete HomeBuilder class for constructing houses def _build_floor(self): self.constructed_object.floor = &#8216;One&#8217; # Alter the Building&#8217;s floor attribute. def _build_size(self): self.constructed_object.size = &#8216;Big&#8217; # Alter the Building&#8217;s size attribute. class FlatBuilder(HomeBuilder): # A concrete HomeBuilder class for constructing flats def _build_floor(self): self.constructed_object.floor = &#8216;More than one&#8217; # Alter the Building&#8217;s floor attribute. def _build_size(self): self.constructed_object.size = &#8216;Small&#8217; # Alter the Building&#8217;s size attribute. class HomeDirector(Director): # A Director class for managing home construction. def construct(self): self.builder.build(&#8216;floor&#8217;) # Build the floor part of the Building by using the keyword &#8216;floor&#8217; self.builder.build(&#8216;size&#8217;) # Build the size part of the Building by using the keyword &#8216;size&#8217; home_director = HomeDirector() home_director.builder = HouseBuilder() # Use the house builder. home_director.construct() # Construct the house. house = home_director.get_constructed_object() # Get the constructed house. print(repr(house)) #Floor: One | Size: Big home_director.builder = FlatBuilder() # Use the flat builder. home_director.construct() # Construct the flat. house = home_director.get_constructed_object() # Get the constructed flat. print(repr(house)) #Floor: More than one | Size: Small<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#factory-pattern\"><\/a>\u5de5\u5382\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u7528\u4e8e\u521b\u5efa\u5bf9\u8c61\u7684\u63a5\u53e3\u3002from pypattyrn.creational.factory import Factory # This is just an interface class Cat(object): def speak(self): print(&#8216;meow&#8217;) class Dog(object): def speak(self): print(&#8216;woof&#8217;) class AnimalFactory(Factory): # A factory class for creating animals. def create(self, animal_type): # Implement the abstract create method. if animal_type == &#8216;cat&#8217;: return Cat() elif animal_type == &#8216;dog&#8217;: return Dog() else: return None animal_factory = AnimalFactory() cat = animal_factory.create(&#8216;cat&#8217;) dog = animal_factory.create(&#8216;dog&#8217;) cat.speak() # &#8216;meow&#8217; dog.speak() # &#8216;woof&#8217;<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#abstract-factory-pattern\"><\/a>\u62bd\u8c61\u5de5\u5382\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u4ece\u4e00\u7cfb\u5217\u5de5\u5382\u521b\u5efa\u4e00\u4e2a\u5b9e\u4f8b\u3002from pypattyrn.creational.factory import Factory, AbstractFactory class Cat(object): def speak(self): print(&#8216;meow&#8217;) class Dog(object): def speak(self): print(&#8216;woof&#8217;) class Ant(object): def march(self): print(&#8216;march&#8217;) class Fly(object): def fly(self): print(&#8216;fly&#8217;) class AnimalFactory(Factory): # A factory class for creating animals. def create(self, animal_type): # Implement the abstract create method. if animal_type == &#8216;cat&#8217;: return Cat() elif animal_type == &#8216;dog&#8217;: return Dog() else: return None class InsectFactory(Factory): # A factory class for creating insects. def create(self, insect_type): # Implement the abstract create method. if insect_type == &#8216;ant&#8217;: return Ant() elif insect_type == &#8216;fly&#8217;: return Fly() else: return None class CreatureFactory(AbstractFactory): # A Factory class for creating creatures. def __init__(self): super().__init__() self._register(&#8216;insect_factory&#8217;, InsectFactory()) # Register an InsectFactory with a keyword. self._register(&#8216;animal_factory&#8217;, AnimalFactory()) # Register an AnimalFactory with a keyword. def create(self, creature_type): # Implement the Abstract create method. if creature_type == &#8216;cat&#8217; or creature_type == &#8216;dog&#8217;: return self._factories[&#8216;animal_factory&#8217;].create(creature_type) # Use the AnimalFactory elif creature_type == &#8216;ant&#8217; or creature_type == &#8216;fly&#8217;: return self._factories[&#8216;insect_factory&#8217;].create(creature_type) # Use the InsectFactory else: return None creature_factory = CreatureFactory() cat = creature_factory.create(&#8216;cat&#8217;) dog = creature_factory.create(&#8216;dog&#8217;) ant = creature_factory.create(&#8216;ant&#8217;) fly = creature_factory.create(&#8216;fly&#8217;) cat.speak() # &#8216;meow&#8217; dog.speak() # &#8216;woof&#8217; ant.march() # &#8216;march&#8217; fly.fly() # &#8216;fly&#8217;<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#object-pool-pattern\"><\/a>\u5bf9\u8c61\u6c60\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u63d0\u4f9b\u4e00\u4e2a\u5b9e\u4f8b\u5316\u5bf9\u8c61\u6c60\uff0c\u53ef\u4ee5\u68c0\u51fa\u5e76\u8fd4\u56de\u8fd9\u4e9b\u5bf9\u8c61\uff0c\u800c\u4e0d\u662f\u4e00\u76f4\u521b\u5efa\u65b0\u5bf9\u8c61\u3002from pypattyrn.creational.pool import Reusable, Pool class Dog(Reusable): def __init__(self, sound): self.sound = sound super().__init__() class DogPool(Pool): def __init__(self): super().__init__(Dog, &#8216;woof&#8217;) dog_pool = DogPool() dog_one = dog_pool.acquire() dog_two = dog_pool.acquire() dog_two.sound = &#8216;meow&#8217; dog_pool.release(dog_one) dog_three = dog_pool.acquire() dog_pool.release(dog_two) dog_four = dog_pool.acquire() assert id(dog_one) == id(dog_three) assert id(dog_two) == id(dog_four) assert dog_one.sound == dog_two.sound assert dog_three.sound == dog_four.sound assert dog_one.sound == dog_four.sound<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#prototype-pattern\"><\/a>\u539f\u578b\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u514b\u9686\u4e00\u4e2a\u5bf9\u8c61\u4ee5\u4ea7\u751f\u65b0\u7684\u5bf9\u8c61\u3002from pypattyrn.creational.prototype import Prototype class Point(Prototype): def __init__(self, x, y): self.x = x self.y = y def move(self, x, y): self.x += x self.y += y point_one = Point(15, 15) point_two = point_one.prototype(z=20) point_three = point_two.prototype() assert point_one.x == point_two.x assert point_one.y == point_two.y assert not hasattr(point_one, &#8216;z&#8217;) assert hasattr(point_two, &#8216;z&#8217;) assert point_two.z == 20 assert point_three.__dict__ == point_two.__dict__ from math import sqrt def distance_to(this, other): return sqrt((this.x &#8211; other.x) ** 2 + (this.y &#8211; other.y) ** 2) point_four = point_three.prototype(distance_to=distance_to) assert hasattr(point_four, &#8216;distance_to&#8217;) assert point_four.distance_to(point_three) == 0<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#singleton-pattern\"><\/a>\u5355\u4f8b\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u786e\u4fdd\u7c7b\u53ea\u5b58\u5728\u4e00\u4e2a\u5b9e\u4f8b\u3002from pypattyrn.creational.singleton import Singleton class DummySingletonOne(object, metaclass=Singleton): def __init__(self): pass class DummySingletonTwo(object, metaclass=Singleton): def __init__(self): pass dummy_class_one_instance_one = DummySingletonOne() dummy_class_one_instance_two = DummySingletonOne() dummy_class_two_instance_one = DummySingletonTwo() dummy_class_two_instance_two = DummySingletonTwo() assert id(dummy_class_one_instance_one) == id(dummy_class_one_instance_two) assert id(dummy_class_two_instance_one) == id(dummy_class_two_instance_two) assert id(dummy_class_one_instance_one) != id(dummy_class_two_instance_one) assert id(dummy_class_one_instance_two) != id(dummy_class_two_instance_two)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#structural-patterns\"><\/a>\u7ed3\u6784\u6a21\u5f0f<\/h4>\n\n\n\n<p>\u5904\u7406\u5bf9\u8c61\u7ec4\u5408\u7684\u6a21\u5f0f<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#adapter-pattern\"><\/a>\u9002\u914d\u5668\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u5c06\u5bf9\u8c61\u5305\u88c5\u5230\u5ba2\u6237\u7aef\u671f\u671b\u7684\u63a5\u53e3\u4e2d\u3002from pypattyrn.structural.adapter import Adapter class Dog(object): def __init__(self): self.name = &#8220;Dog&#8221; def bark(self): return &#8220;woof!&#8221; class Cat(object): def __init__(self): self.name = &#8220;Cat&#8221; def meow(self): return &#8220;meow!&#8221; cat = Cat() dog = Dog() cat_adapter = Adapter(cat, make_noise=cat.meow) dog_adapter = Adapter(dog, make_noise=dog.bark) assert cat_adapter.make_noise == cat.meow assert dog_adapter.make_noise == dog.bark assert cat_adapter.make_noise() == &#8216;meow!&#8217; assert dog_adapter.make_noise() == &#8216;woof!&#8217; assert cat_adapter.name == &#8216;Cat&#8217; assert dog_adapter.name == &#8216;Dog&#8217; assert cat_adapter.meow() == &#8216;meow!&#8217; assert dog_adapter.bark() == &#8216;woof!&#8217; assert cat_adapter.original_dict() == cat.__dict__ assert dog_adapter.original_dict() == dog.__dict__ bad_cat_adapter = Adapter(cat, foo=cat.name) try: bad_cat_adapter.foo except AttributeError: pass else: raise AssertionError() bad_dog_adapter = Adapter(dog, make_noise=cat.meow) try: bad_dog_adapter.make_noise() except AttributeError: pass else: raise AssertionError()<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#composite-pattern\"><\/a>\u590d\u5408\u56fe\u6848<\/h5>\n\n\n\n<p>\u5c06\u5bf9\u8c61\u7ec4\u6210\u4e00\u4e2a\u53ef\u4ee5\u7edf\u4e00\u5904\u7406\u7684\u5bf9\u8c61\u6811\u7ed3\u6784\u3002from pypattyrn.structural.composite import Composite class Component(object): def do_something(self): pass class Leaf(Component): def __init__(self): self.did_something = False def do_something(self): self.did_something = True leaf_one = Leaf() leaf_two = Leaf() leaf_three = Leaf() composite_one = Composite(Component) composite_two = Composite(Component) composite_three = Composite(Component) composite_one.add_component(leaf_one) composite_two.add_component(leaf_two) composite_three.add_component(leaf_three) composite_two.add_component(composite_three) composite_one.add_component(composite_two) assert set() == {leaf_one, composite_two}.symmetric_difference(composite_one.components) assert set() == {leaf_two, composite_three}.symmetric_difference(composite_two.components) assert set() == {leaf_three}.symmetric_difference(composite_three.components) composite_two.remove_component(composite_three) assert set() == {leaf_two}.symmetric_difference(composite_two.components) assert not leaf_one.did_something assert not leaf_two.did_something assert not leaf_three.did_something composite_one.do_something() assert leaf_one.did_something assert leaf_two.did_something assert not leaf_three.did_something<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#decorator-pattern\"><\/a>\u88c5\u9970\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u5c06\u9644\u52a0\u529f\u80fd\u9644\u52a0\u5230\u51fd\u6570\u4e0a\u3002import time from pypattyrn.structural.decorator import DecoratorSimple, DecoratorComplex, CallWrapper class TimeThis(DecoratorSimple): def __call__(self, *args, **kwargs): start = time.time() result = self.func(*args, **kwargs) end = time.time() &#8211; start return result, end class SlowClass(object): @TimeThis def slow_function(self, n): time.sleep(n) return &#8216;foo&#8217; slow_class = SlowClass() result = slow_class.slow_function(1) assert result[0] == &#8216;foo&#8217; assert 1 &lt;= result[1] &lt;= 2 class Alert(DecoratorComplex): def __init__(self, alert_time): self.alert_time = alert_time @CallWrapper def __call__(self, func, *args, **kwargs): start = time.time() return_val = func(*args, **kwargs) end = time.time() &#8211; start if end &gt; self.alert_time: return return_val, True return return_val, False class SlowClass(object): @Alert(1) def slow_function_true(self, n): time.sleep(n) return n @Alert(1) def slow_function_false(self, n): return n slow_class = SlowClass() assert (2, True) == slow_class.slow_function_true(2) assert (10, False) == slow_class.slow_function_false(10)<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><a href=\"https:\/\/github.com\/tylerlaberge\/PyPattyrn#flyweight-pattern\"><\/a>\u4eab\u5143\u6a21\u5f0f<\/h5>\n\n\n\n<p>\u4e0e\u5176\u4ed6\u7c7b\u4f3c\u5bf9\u8c61\u5171\u4eab\u6570\u636e\u4ee5\u63d0\u9ad8\u6548\u7387\u3002from pypattyrn.structural.flyweight import FlyweightMeta class Card(object, metaclass=FlyweightMeta): def __init__(self, suit, value): self.suit = suit self.value = value three_of_spades = Card(&#8216;Spade&#8217;, 3) four_of_spades = Card(&#8216;Spade&#8217;, 4) three_of_spades_two = Card(&#8216;Spade&#8217;, 3) assert id(three_of_spades) == id(three_of_spades_two) assert id(three_of_spades) != id(four_of_spades)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PyPattyrn \u662f\u4e00\u4e2a\u5b9e\u7528\u7684 Python \u5305\uff0c\u5b83\u6c47\u96c6\u4e86\u5404\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u7684\u901a\u7528\u4ee3\u7801\uff0c\u4ee5\u4fbf\u4e8e\u5f00\u53d1\u8005\u4eec\u5728\u81ea\u5df1\u7684\u9879\u76ee [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"class_list":["post-708","post","type-post","status-publish","format-standard","hentry","category-python"],"blocksy_meta":"","_links":{"self":[{"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/posts\/708","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=708"}],"version-history":[{"count":1,"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/posts\/708\/revisions"}],"predecessor-version":[{"id":711,"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/posts\/708\/revisions\/711"}],"wp:attachment":[{"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=708"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ai.gitpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}