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的设计原则及设计模式的更多相关文章

  1. 连载:面向对象的葵花宝典:思考、技巧与实践(39) - 设计原则 vs 设计模式

    它的设计原则,和设计模式,是否该用它? ============================================================================= 在& ...

  2. 《设计模式之美》 <03>面向对象、设计原则、设计模式、编程规范、重构,这五者有何关系?

    面向对象 现在,主流的编程范式或者是编程风格有三种,它们分别是面向过程.面向对象和函数式编程.面向对象这种编程风格又是这其中最主流的.现在比较流行的编程语言大部分都是面向对象编程语言.大部分项目也都是 ...

  3. Design Principle vs Design Pattern 设计原则 vs 设计模式

    Design Principle vs Design Pattern设计原则 vs 设计模式 来源:https://www.tutorialsteacher.com/articles/differen ...

  4. UML建模语言、设计原则、设计模式

    1.UML统一建模语言 定义:用于软件系统设计与分析的语言工具 目的:帮助开发人员更好的梳理逻辑.思路 学习地址:UML概述_w3cschool 官网:https://www.omg.org/spec ...

  5. javaSE高级篇7 — 设计原则和设计模式 — 设计模式慢慢更( 这是思想层次篇 )

    1.什么是设计原则? 设计原则就是面向对象的原则嘛,即:OOP原则 换句话说:就是为了处理类与类之间的关系( 包括接口.类中的方法 ) 2.OOP设计原则有哪些? 1).开闭原则:就是指对拓展开放.对 ...

  6. Android设计原则和设计模式

    1. 设计模式的六大基本原则 1.0 总结: 因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定.而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们 ...

  7. C#设计模式(0)——设计原则

    设计原则 使用设计模式的根本原因是适应变化,提高代码复用率,使软件更具有可维护性和可扩展性.在进行设计的时候,我们需要遵循以下几个原则:单一职责原则.开闭原则.里氏替代原则.依赖倒置原则.接口隔离原则 ...

  8. 【OOAD】面向对象设计原则概述

    软件的可维护性和可复用性 知名软件大师Robert C.Martin认为一个可维护性(Maintainability) 较低的软件设计,通常由于如下4个原因造成: 过于僵硬(Rigidity)  ...

  9. SOLID 设计原则 In C# 代码实现

    [S] Single Responsibility Principle (单一职责原则) 认为一个对象应该仅只有一个单一的职责 namespace SingleResponsibilityPrinci ...

随机推荐

  1. selenium加载配置参数,让chrome浏览器不出现‘Chrome正在受到自动软件的控制’的提示语,以及后台静默模式启动自动化测试,不占用桌面的方法

    一:自动化测试的时候,启动浏览器出现‘Chrome正在受到自动软件的控制’,怎么样隐藏,今天学习分享: 在浏览器配置里加个参数,忽略掉这个警告提示语,disable_infobars option = ...

  2. Makedown

    目录 Makedown 介绍 Markdown的语法 Makedown 介绍 Makedown的创建者是John Gruber Q:什么是markdown呢? markdown和html类似是mark ...

  3. js 颜色16进制转RGB方法

    //颜色16进制转RGB方法 String.prototype.colorRgb = function(){ var sColor = this.toLowerCase(); //十六进制颜色值的正则 ...

  4. 让priority_queue支持小根堆的几种方法

    点击这里了解什么是priority_queue 前言 priority_queue默认是大根堆,也就是大的元素会放在前面 例如 #include<iostream> #include< ...

  5. 基于 CODING 的 Spring Boot 持续集成项目

    本文作者:CODING 用户 - 廖石荣 持续集成的概念 持续集成(Continuous integration,简称 CI)是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少 ...

  6. 【Dojo 1.x】笔记2 使用服务器环境及使用模块

    又开坑了.上次静态html页面完成本地module的引用,算是成功了,但是并不知道是怎么运作的,没关系慢慢来. 我用的环境是VSCode,这次因为官方说要在服务器环境下运行,所以就用上了VSCode的 ...

  7. 解决Centos7 yum 出现could not retrieve mirrorlist 错误

    刚通过VMware12安装了centos7.x后,使用ip addr查看centos局域网的ip发现没有,使用yum安装一些工具包时也出现报错: Loaded plugins: fastestmirr ...

  8. 解决一个Ubuntu中编译NEON优化的OpenCV的错误

    在Ubuntu 16中编译开启NEON优化的Opencv时,遇到libpng编译是使用汇编代码的错误,完整错误见文章末尾.通过查询发现解决方案是安装跨平台编译器,安装代码如下: sudo apt-ge ...

  9. Django2.0 正则表示匹配的简单例子

    在Django中,使用正则表达式,匹配Url 默认情况下,url固定格式如下: urlpatterns = [ path('admin/', admin.site.urls), ] 如果需要使用正则表 ...

  10. 深入理解Mysql索引的底层数据结构 B+ Tree (1)

    关键字的个数等于路的个数减1. 一个二叉树节点可以存储4kb大小的数据,假如关键字是整型的一个关键字占用4byte,其他数据冗余4个字节 4 kb = 4*1024 byte = 4096 byte. ...