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】
当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。
python的设计原则及设计模式的更多相关文章
- 连载:面向对象的葵花宝典:思考、技巧与实践(39) - 设计原则 vs 设计模式
它的设计原则,和设计模式,是否该用它? ============================================================================= 在& ...
- 《设计模式之美》 <03>面向对象、设计原则、设计模式、编程规范、重构,这五者有何关系?
面向对象 现在,主流的编程范式或者是编程风格有三种,它们分别是面向过程.面向对象和函数式编程.面向对象这种编程风格又是这其中最主流的.现在比较流行的编程语言大部分都是面向对象编程语言.大部分项目也都是 ...
- Design Principle vs Design Pattern 设计原则 vs 设计模式
Design Principle vs Design Pattern设计原则 vs 设计模式 来源:https://www.tutorialsteacher.com/articles/differen ...
- UML建模语言、设计原则、设计模式
1.UML统一建模语言 定义:用于软件系统设计与分析的语言工具 目的:帮助开发人员更好的梳理逻辑.思路 学习地址:UML概述_w3cschool 官网:https://www.omg.org/spec ...
- javaSE高级篇7 — 设计原则和设计模式 — 设计模式慢慢更( 这是思想层次篇 )
1.什么是设计原则? 设计原则就是面向对象的原则嘛,即:OOP原则 换句话说:就是为了处理类与类之间的关系( 包括接口.类中的方法 ) 2.OOP设计原则有哪些? 1).开闭原则:就是指对拓展开放.对 ...
- Android设计原则和设计模式
1. 设计模式的六大基本原则 1.0 总结: 因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定.而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们 ...
- C#设计模式(0)——设计原则
设计原则 使用设计模式的根本原因是适应变化,提高代码复用率,使软件更具有可维护性和可扩展性.在进行设计的时候,我们需要遵循以下几个原则:单一职责原则.开闭原则.里氏替代原则.依赖倒置原则.接口隔离原则 ...
- 【OOAD】面向对象设计原则概述
软件的可维护性和可复用性 知名软件大师Robert C.Martin认为一个可维护性(Maintainability) 较低的软件设计,通常由于如下4个原因造成: 过于僵硬(Rigidity) ...
- SOLID 设计原则 In C# 代码实现
[S] Single Responsibility Principle (单一职责原则) 认为一个对象应该仅只有一个单一的职责 namespace SingleResponsibilityPrinci ...
随机推荐
- 内存管理-MRC与ARC详解
Objective-C提供了两种内存管理机制MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),为Objective-C提 ...
- [Go] golang的error接口
error接口1.error就是一个接口interface2.属于errors包,该包有一个导出方法New,返回了errorString类型3.errorString类型实现了error接口4.之所以 ...
- PHP数组array_multisort排序详解
今天特意再看了下官网的介绍,对它的多个数组的排序还是每台理解,找了些资料深入理解了下,在此总结下. PHP中array_multisort函数对多个数组或多维数组进行排序,关联(string)键名保持 ...
- 学JAVA第五天,今天困得要死
好不容易坚持到第五天了,继续继续!!! 今天老师没有讲JAVA的for循环,倒是讲了HTML的相关内容: 讲了JAVA代码怎么在HTML中运行. 只要在HTML加入这个 background-colo ...
- Hdu 3001 Travelling 状态DP
题目大意 一次旅游,经过所有城市至少一次,并且任何一座城市访问的次数不能超过两次,求最小费用 每个城市最多访问两次,用状态0,1,2标识访问次数 把城市1~N的状态按照次序连接在一起,就组成了一个三进 ...
- SpringBoot 整合 apollo
简介 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理场景 ...
- break,return和continue三者区别(Java)
一.break用于完全结束一个循环,跳出循环体. 不管是哪种循环,一旦在循环体中遇到break,系统将完全结束循环,开始执行循环之后的代码. class Demo3 { public static v ...
- 深入浅出Java类加载过程
学习笔记二之Java虚拟机中类加载的过程 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现这个类进行初始化. 1. 加载 加载,是指Java虚拟机查找字 ...
- 分享一些 Windows 平台上的神器
下面分享一些 Windows 平台上日常开发使用的软件,有些软件我自认为是神器,可以大大提高效率. 编辑器类软件 IntelliJ IDEA IntelliJ IDEA 内部集成 Java 开发环境, ...
- 程序员50题(JS版本)(三)
程序11:判断101~200之间有多少个素数,并输出所有素数 for(var i=101,num=0;i<=200;i++){ for(var j=2;j<=i;j++){ if(i%j= ...