python的设计原则及设计模式
python的设计原则及设计模式
七大设计原则
单一职责原则
【SINGLE RESPONSIBILITY PRINCIPLE】
一个类负责一项职责。
里氏替换原则
【LISKOV SUBSTITUTION PRINCIPLE】
继承与派生的规则。(子类可替换父类)
依赖倒转原则
【DEPENDENCE INVERSION PRINCIPLE】
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程。
接口隔离原则
【INTERFACE SEGREGATION PRINCIPLE】
建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。
迪米特法则
【LOW OF DEMETER】
高内聚 低耦合 – high cohesion low coupling
开闭原则
【OPEN CLOSE PRINCIPLE】
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
组合/聚合复用原则
【Composition/Aggregation Reuse Principle(CARP) 】
尽量使用组合和聚合少使用继承的关系来达到复用的原则。
24种设计模式
创建型模式
工厂模式
【Factory method pattern】
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
例子:
1、 我们有一个基类Person ,包涵获取名字,性别的方法 。有两个子类male 和female,可以打招呼。还有一个工厂类。
2、 工厂类有一个方法名getPerson有两个输入参数,名字和性别。
3、 用户使用工厂类,通过调用getPerson方法。
在程序运行期间,用户传递性别给工厂,工厂创建一个与性别有关的对象。因此工厂类在运行期,决定了哪个对象应该被创建。
class Person: def __init__(self): self.name = None self.gender = None def getName(self): return self.name def getGender(self): return self.gender class Male(Person): def __init__(self, name): print "Hello Mr." + name class Female(Person): def __init__(self, name): print "Hello Miss." + name class Factory: def getPerson(self, name, gender): if gender == ‘M': return Male(name) if gender == 'F': return Female(name) if __name__ == '__main__': factory = Factory() person = factory.getPerson("Chetan", "M")
抽象工厂模式
【Abstract factory pattern】
提供一个接口, 用于创建相关或依赖对象的家族, 而不需要指定具体类。
import random class PetShop(object): def __init__(self,animal_factory=None): # pet 宠物 factory 工厂 self.pet_factory = animal_factory def show_pet(self): pet = self.pet_factory.get_pet() print("this is a lovely", pet) print("it says",pet.speak()) print("it eats",self.pet_factory.get_food()) class Dog: def speak(self): return "Dog" def __str__(self): return "this is Dog" class Cat: def speak(self): return "Cat" def __str__(self): return "this is Cat" class CatFactory: def get_pet(self): return Cat() def get_food(self): return "cat food" class DogFactory: def get_pet(self): return Dog() def get_food(self): return "dog food" def get_factory(): return random.choice([DogFactory,CatFactory]) if __name__ == '__main__': shop = PetShop() # pet_factory 默认为None,后面延迟加载 shop.pet_factory = get_factory()() # 延迟加载,随机选择一个工厂然后实例出来一个对象给商店 shop.show_pet()
生成器模式(建造者模式)
【Builder pattern】
使用生成器模式封装一个产品的构造过程,并允许按步骤构造。将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
class Director: # director 监视 def __init__(self): self.builder = None # builder建造者 def construct_building(self): self.builder.new_building() self.builder.build_floor() self.builder.build_size() def get_building(self): return self.builder.building class Builder: def __init__(self): self.building = None def new_building(self): self.building = Building() class Building: def __init__(self): self.floor = None self.size = None def __repr__(self): # 和__str__ 魔法方法类似,都是打印对象的时候调用,不过repr更强大 # repr方法在交互式环境下也能起作用,即交互式环境直接输变量名打印的时候 # __str__ 只有在print的时候才会触发 return "Floor:%s | Size: %s" % (self.floor,self.size) class BuilderHouse(Builder): def build_floor(self): self.building.floor = "One" def build_size(self): self.building.size = "Big" class BuilderFlat(Builder): # flat 公寓 def build_floor(self): self.building.floor = "More than One" def build_size(self): self.building.size = "small" if __name__ == '__main__': director = Director() director.builder = BuilderHouse() director.construct_building() building = director.get_building() print(building) director.builder = BuilderFlat() director.construct_building() building = director.get_building() print(building)
原型模式
【Prototype pattern】
当创建给定类的实例过程很昂贵或很复杂时,就使用原形模式。
单例模式
【Singleton pattern】
确保一个类只有一个实例,并提供全局访问点。
class A(object): __obj = False __init = False def __init__(self, name): if not A.__init: self.name = name A.__init = True def __new__(cls, *args, **kwargs): if not A.__obj: A.__obj = super().__new__(cls) return A.__obj if __name__ == '__main__': # 只初始化一次的单例模式 a = A("nick") b = A("nick2") print(a.name) # nick print(b.name) # nick print(a == b) # True print(id(a), id(b)) # 54527760 54527760
多例模式
【Multition pattern】
在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。
结构型模式
适配器模式
【Adapter pattern】
将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。对象适配器使用组合,类适配器使用多重继承。
import os class Dog: def __init__(self): self.name ="Dog" def bark(self): # bark :叫声 return "woof!" # woof 低吠声 class Cat: def __init__(self): self.name = "Cat" def meow(self): # meow 猫叫声 return "meow" # meow 猫叫声 class Human: def __init__(self): self.name = "Human" def speak(self): return "hello, python" class Car: def __init__(self): self.name = "Car" def make_noise(self, noise_level): return "noise level is {}".format(noise_level) class Adapter: # adapter 适配器 def __init__(self,obj,adapted_methods): # adpted 适应 self.obj = obj self.__dict__.update(adapted_methods) # self.__dict__是打印对象所有的属性,结果是一个字典 {"kye":value} # key对应对象的属性,value对应属性的属性值。这里就相当于把不同类的方法都绑定到Adapter这个类实例化出来的 # 对象的make_noise 属性上面去,该属性的值对应其他类里面的方法。 def __getattr__(self, attr): # 当调用类不存的属性或者方法时,就会触发该魔法方法 return getattr(self.obj, attr) # getattr(object,attr [,default]) def main(): objects = [] dog = Dog() objects.append(Adapter(dog,dict(make_noise=dog.bark))) cat = Cat() objects.append(Adapter(cat,dict(make_noise=cat.meow))) human = Human() objects.append(Adapter(human,dict(make_noise=human.speak))) car = Car() car_noise = lambda : car.make_noise(3) objects.append(Adapter(car,dict(make_noise=car_noise))) for obj in objects: print("A",obj.name,"goes",obj.make_noise()) # 这里 obj.make_noise 就相当于 dog.bark 这些方法,后面加括号代表执行 print(obj.obj) # 原来的对象被存储到obj属性里面. if __name__ == '__main__': # 适配器模式在不改变原有类的基础上,统一了所有的方法,还能够保存原有对象的引用obj属性 main()
桥接模式
【Bridge pattern】
使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。
class DrawingAPI1: def draw_circle(self, x, y, radius): print("API1.circle at {} : {} ,radius:{}".format(x, y, radius)) class DrawingAPI2: def draw_circle(self,x,y,radius): print("API2.cirle at {} : {} ,radius:{}".format(x, y, radius)) class CircleShape: def __init__(self,x,y,radius,drawing_api): self._x = x self._y = y self._radius = radius self._drawing_api = drawing_api def draw(self): self._drawing_api.draw_circle(self._x,self._y,self._radius) def scale(self,pct): # scale 规模 self._radius *= pct # pct 百分比 def main(): shapes = ( CircleShape(1,2,3,DrawingAPI1()), CircleShape(5,7,11,DrawingAPI2()), ) # 提供2个 for shape in shapes: shape.scale(2.5) shape.draw() if __name__ == '__main__': # 桥接模式就是一个类的属性的值是另一个类的实例对象。然后可以通过这个类的实例对象去调用另外一个类对象的方法 main()
组合模式
【Composite pattern】
允许你将对象组合成树形结构来表现‘整体/部分’层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
装饰器模式
【Decorator pattern】
动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
class foo(object): def f1(self): print("func f1") def f2(self): print("func f2") class foo_decorator(object): def __init__(self,decorator): self._decorator = decorator def f1(self): print("decorator f1") self._decorator.f1() def __getattr__(self, item): # 当得不到想要的属性时,就去自己的装饰里面拿,使用 getattr()内建方法 return getattr(self._decorator,item) if __name__ == '__main__': # 主要思想还是使用魔法方法 __getattr__ 方法, 然后把另外一个对象赋值到自身的属性上面. # 添加一个运行另外一个对象的接口,没有接口时,就去直接调用另一个对象的方法. u = foo() d = foo_decorator(u) d.f1() d.f2()
外观模式
【Facade pattern】
提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
class small_or_piece1: def __init__(self): pass def do_small1(self): print('do small 1') class small_or_piece_2: def __init__(self): pass def do_small2(self): print('do small 2') class small_or_piece_3: def __init__(self): pass def do_small3(self): print('do small 3') class outside: def __init__(self): self.__small1 = small_or_piece1() self.__small2 = small_or_piece_2() self.__small3 = small_or_piece_3() def method1(self): self.__small1.do_small1() ##如果这里调用的不只2两函数,作用就显示出来了,可以把原本复杂的函数调用关系清楚化,统一化 self.__small2.do_small2() def method2(self): self.__small2.do_small2() self.__small3.do_small3() if __name__ == '__main__': # 外观模式应用于在很多复杂而小功能需要调用时,并且这些调用还具有一定的相关性,即一调用就是一系列的调用. osd = outside() osd.method1() osd.method2()
亨元模式
【Flyweight Pattern】
如想让某个类的一个实例能用来提供许多‘虚拟实例’,就使用蝇量模式。
代理模式
【Proxy pattern】
为另一个对象提供一个替身或占位符以控制对这个对象的访问。
行为型模式
解释器模式
【Interpreter pattern】
使用解释器模式为语言创建解释器。
模板方法模式
【Template pattern】
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
责任链模式
【Chain of responsibility pattern】
通过责任链模式,你可以为某个请求创建一个对象链。每个对象依序检查此请求并对其进行处理或者将它传给链中的下一个对象。
class Handler: def __init__(self): self.successor = None def add_successor(self,successor): # successor 后续的事,继承者 self.successor = successor class ConcreteHandler1(Handler): def handle(self,request): if request>0 and request<=10: print("concreteHandler1 deal %s"%request) elif self.successor is not None: self.successor.handle(request) else: print("no handler can deal with %s"%request) class ConcreteHandler2(Handler): def handle(self,request): if request>10 and request<=20: print("ConcreteHandler2 deal %s"%request) elif self.successor is not None: self.successor.handle(request) else: print("no handler can deal with %s" % request) class ConcreteHandler3(Handler): def handle(self,request): if request>20 and request<=30: print("ConcreteHandler3 deal %s"%request) elif self.successor is not None: self.successor.handle(request) else: print("no handler can deal with %s" % request) if __name__ == '__main__': h1 = ConcreteHandler1() # 创建处理者1 h2 = ConcreteHandler2() # 创建处理者2 h3 = ConcreteHandler3() # 创建处理者3 h1.add_successor(h2) # 添加h1如果处理不了就让h2去处理 h2.add_successor(h3) # 如果h2处理不了就让h3去处理 requests = [1,3,23,42,34,67,11,22,14,36] for request in requests: h1.handle(request)
命令模式
【Command pattern】
将”请求”封闭成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
import os class MoveFileCommand(object): def __init__(self,src,dest): self.src = src self.dest = dest def execute(self): self() # 直接调用对象本身会执行__call__方法 def __call__(self, *args, **kwargs): # __call__ 魔法方法直接调用对象的时候执行的方法 print("renaming {} to {}".format(self.src,self.dest)) os.rename(self.src,self.dest) def undo(self): print("renaming {} to {}".format(self.dest,self.src)) os.rename(self.dest,self.src) if __name__ == '__main__': command_stack = [] command_stack.append(MoveFileCommand("foo.txt","bar.txt")) command_stack.append(MoveFileCommand("bar.txt","foo.txt")) for cmd in command_stack: cmd.execute() for cmd in reversed(command_stack): cmd.undo()
迭代器模式
【Iterator pattern】
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
中介者模式
【Mediator pattern】
使用中介者模式来集中相关对象之间复杂的沟通和控制方式。
备忘录模式
【Memento pattern】
当你需要让对象返回之前的状态时(例如,你的用户请求‘撤销’), 你使用备忘录模式。
观察者模式
【Observer pattern】
在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
状态模式
【State pattern】
允许对象在内部状态改变时改变它的行为,对象看起来好象改了它的类。
策略模式
【Strategy pattern】
定义了算法族,分别封闭起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
访问者模式
【Visitor pattern】
当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。