鸭子类型介绍

鸭子类型 定义 鸭子类型(英语:duck typing)在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合“决定。这个概念的名字来源于由詹姆斯·惠特科姆·莱利提出的鸭子测试(见下面的“历史”章节),“鸭子测试”可以这样表述: ​ “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为"鸭子"的对象,并调用它的"走"和"叫"方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的"走"和"叫"方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的"走"和"叫"方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。 鸭子类型通常得益于"不"测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。 在常规类型中,我们能否在一个特定场景中使用某个对象取决于这个对象的类型,而在鸭子类型中,则取决于这个对象是否具有某种属性或者方法——即只要具备特定的属性或方法,能通过鸭子测试,就可以使用。 多态 为什么会在鸭子类型中去介绍多态这个东西,众所周知,面向对象编程的三大特点 继承、封装、多态 ...

6 min · 2634 words · Luenci

行为型模式

行为型模式 行为型模式,顾名思义,它主要关注的是对象的责任。 它们关注对象之间的交互以及对象的响应性 对象应该能够交互,同时仍然保持松散耦合 观察者模式 在观察者设计模式中,对象(主题)维护了一个依赖(观察者)列表,以便主题可以使用观察者定义的任何方法通知所有观察者它所发生的变化。 它定义了对象之间的一对多的依赖关系,从而使得一个对象中的任何更改都将自动通知给其他对象 它封装了主题的核心组件 UML图 主题(Subject):类Subject需要了解Observe。Subject类具有许多方法,诸如register()和deregister()等,Observer可以通过这些方法注册到Subject类中。因此,一个Subject可以处理多个Observe。 观察者(Observe):它为关注主题的对象定义了一个接口。它定义了Observe需要实现的各个方法,以便在主题发生变化时能够获得相应的通知。 具体观察者(ConcreteObserver):它用来保存应该与Subject的状态保持一致的状态。它实现了Observe接口以保持其状态与主题中的变化相一致。 代码案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #!/usr/bin/env python # -*- coding: utf-8 -*- class Subject(object): def __init__(self): self.__observer = [] def register(self, observer): self.__observer.append(observer) def notifyAll(self, *args, **kwargs): for observer in self.__observer: observer.notify(self, *args, **kwargs) class Observer1(object): def __init__(self, subject): subject.register(self) def notify(self, subject, *args): print(f"{type(self).__name__}:: Got, {args} from {subject}") class Observer2(object): def __init__(self, subject): subject.register(self) def notify(self, subject, *args): print(f"{type(self).__name__}:: Got, {args} from {subject}") if __name__ == '__main__': subject = Subject() observer1 = Observer1(subject) observer2 = Observer2(subject) subject.notifyAll("notify~~~") 观察者模式的优点和缺点 优点: 它使得彼此交互的对象之间保持送耦合 它使得我们可以在无需对主题或观察者进行任何修改的情况下高效地发送数据到其他对象 可以随时添加/删除观察者 缺点: 观察者接口必须由具体观察者实现,这涉及继承。无法进行组合,因为观察者接口可以实例化 如果实现不当的话,观察者可能会增加复杂性,并导致性能降低 在软件应用程序中,通知有时可能是不可靠的,并导致竞争条件或不一致性 ...

11 min · 5423 words · Luenci

结构型模式

结构型模式 结构型模式用于设计对象和类的结构,从而使它们之间可以互相协作以获取更大的结构。 结构型模式描述如何将对象和类组合成更大的结构 结构型模式是一种能够简化设计工作的模式,因为它能够找出更简单的方法来认识或表示实体之间的关系。在面向对象世界中,实体指的是对象或类 类模式可以通过继承来描述对象,从而提供更有用的程序接口,而对象模式则描述了如何将对象联系起来从而组合成更大的对象。结构型模式是类和对象模式的综合体 门面设计模式 它为子系统的一组接口提供一个统一的接口,并定义一个高级接口来帮助客户端通过更加简单的方式使用子系统 门面模式解决的问题是,如何用的单个接口对象来表示复杂的子系统。实际上它并不是封装子系统,而是对底层子系统进行组合 它促进了实现与多个客户端的解耦 UML图 代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 #!/usr/bin/env python # -*- coding: utf-8 -*- class EventManager(object): def __init__(self): print("Event Manager:: Let me talk to the folks\\n") def arrange(self): self.hotelier = Hotelier() self.hotelier.bookHotel() self.florist = Florist() self.florist.setFlowerRequirements() self.caterer = Caterer() self.caterer.setCuisine() self.musiccian = Musician() self.musiccian.setMusicType() class Hotelier(object): def __init__(self): print("Arranging the hotel for Marriage ?") def __isAvailable(self): print("Is the Hotel free for the event on given day?") return True def bookHotel(self): if self.__isAvailable(): print("Register the Booking \\n\\n") class Florist(object): def __init__(self): print("Flower Decorations for the Event ? --") def setFlowerRequirements(self): print("Carnations, Rose and Lilies would be used for Decorations\\n\\n") class Caterer(object): def __init__(self): print("Food Arrangements for the Event --") def setCuisine(self): print("Chinese & Continental Cuisine to be served \\n\\n") class Musician(object): def __init__(self): print("Musical Arrangements for the Marriage --") def setMusicType(self): print() class You(object): def __init__(self): print("you::whoa Marriage Arrangements !") def askEventManager(self): print("you:: Let is Contact the Event Manager\\n\\n") em = EventManager() em.arrange() def __del__(self): print("All preparations done!") if __name__ == '__main__': you = You() you.askEventManager() out: you::whoa Marriage Arrangements ! you:: Let is Contact the Event Manager Event Manager:: Let me talk to the folks Arranging the hotel for Marriage ? Is the Hotel free for the event on given day? Register the Booking Flower Decorations for the Event ? -- Carnations, Rose and Lilies would be used for Decorations Food Arrangements for the Event -- Chinese & Continental Cuisine to be served Musical Arrangements for the Marriage -- All preparations done! 小结 EventManager类是简化接口的门面 EventManager 通过组合创建子系统对象,如Hotelier,Florist等。 ...

7 min · 3087 words · Luenci

创建型模式

预备知识 @abstractmethod:抽象方法,含abstractmethod方法的类不能实例化,继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写 @ property:方法伪装属性,方法返回值及属性值,被装饰方法不能有参数,必须实例化后调用,类不能调用 @ classmethod:类方法,可以通过实例对象和类对象调用,被该函数修饰的方法第一个参数代表类本身常用cls,被修饰函数内可调用类属性,不能调用实例属性 @staticmethod:静态方法,可以通过实例对象和类对象调用,被装饰函数可无参数,被装饰函数内部通过类名.属性引用类属性或类方法,不能引用实例属性 创建型模式 创建型模式的工作原理是基于对象的创建机制的。由于这些模式隔离了对象的创建细节。所以使得代码能够与要创建的对象的类型互相独立。 它们的运行机制基于对象的创建方式 它们将对象创建的细节隔离开来 代码与所创建的对象的类型无关 单例模式 单例模式提供了这样一种机制,即确保类有且只有一个特定类型的对象,并提供全局访问点 UML图 代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 In [1]: class Singleton(object): """ 单例模式 """ ...: def __new__(cls): ...: if not hasattr(cls, "instance"): ...: cls.instance = super(Singleton, cls).__new__(cls) ...: return cls.instance ...: In [2]: s = Singleton() In [3]: s Out[3]: <__main__.Singleton at 0x7fc32793ed90> In [4]: s2 = Singleton() In [5]: s2 Out[5]: <__main__.Singleton at 0x7fc32793ed90> In [21]: class Singletons(object): """ 懒汉式加载 """ ...: __instance = None ...: def __init__(self): ...: if not Singletons.__instance: ...: print("__init__ method called..") ...: else: ...: print("Instance alreadly created:",self.getInstance()) ...: @classmethod ...: def getInstance(cls): ...: if not cls.__instance: ...: cls.__instance = Singletons() ...: return cls.__instance ...: In [22]: a = Singletons() __init__ method called.. In [23]: a1 = Singletons() __init__ method called.. In [24]: a2 = Singletons() __init__ method called.. In [25]: a.getInstance() __init__ method called.. Out[25]: <__main__.Singletons at 0x7fc327b020d0> In [26]: a Out[26]: <__main__.Singletons at 0x7fc327e48ca0> In [27]: a1 Out[27]: <__main__.Singletons at 0x7fc32763a250> In [1]: class MyMetaClass(type): """ 元类实现单例模式 """ ...: _instances = {} ...: def __call__(cls,*args,**kwargs): ...: print("**** Here`s my MetaClass ****") ...: if cls not in cls._instances: ...: cls._instances[cls] = super(MyMetaClass,cls).__call__(*args,**kwargs) ...: return cls._instances[cls] In [2]: class test(metaclass=MyMetaClass): ...: pass ...: In [3]: a = test() **** Here`s my MetaClass **** In [4]: a2 = test() **** Here`s my MetaClass **** In [5]: id(a) Out[5]: 139837183079520 In [6]: id(a2) Out[6]: 139837183079520 虽然单例模式在许多情况下效果很好,但是由于单例模式具有全局访问权限,可能会存在一些问题 全局变量可能在某处已经被更改,但是开发人员仍然认为它们没有发生变化,而改变量还在应用程序的其他位置被使用 可能会对同一个对象创建多个应用(此单例类被多次实例化,实际只实例化一次就可以) 所有依赖于全局变量的类都会由于一个类的改变而紧密耦合为全局数据,从而可能在无意中影响另一个类 ...

5 min · 2056 words · Luenci

设计模式

设计模式 设计模式设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。大部分设计模式要解决的都是代码的可扩展性问题。设计模式相对于设计原则来说,没有那么抽象,而且大部分都不难理解,代码实现也并不复杂。这一块的学习难点是了解它们都能解决哪些问题,掌握典型的应用场景,并且懂得不过度应用。 ...

4 min · 1748 words · Luenci