常用设计模式的介绍

  • 一:单例设计模式(创建型模式)
    • 1,单例设计模式理解
    • 2,利用python实现经典的单例模式
    • 3, 懒汉式实例化
    • 4,模块级别的单例模式
    • 5,Monostate 单例模式
    • 6,单例模式缺点
    • 7,单例模式demo
  • 二:工厂模式-建立创建对象的工厂
    • 1,了解工厂模式
    • 2,简单工厂模式
    • 3,工厂方法模式
      • 1,实现工厂方法
      • 2,工厂方法模式的优点
    • 4,抽象工厂模式
      • 1,实现抽象工厂模式
      • 2,工厂方法与抽象工厂
  • 三:门面模式-与门面相适(结构型模式)
    • 1,理解结构型设计模式
    • 2,理解门面设计模式
    • 3,门面设计模式-UML
    • 4,门面模式的实现
    • 5,最少知识原则
  • 四:代理模式-控制对象的方法
    • 1,理解代理设计模式
    • 2,代理模式的uml
    • 3,不同类型的代理
    • 4,代理模式demo
    • 5,门模式与代理模式比较
  • 五:观察者模式-了解对象的情况(行为模式)
    • 1,理解观察者设计模式
    • 3,观察者模式demo
    • 3,观察者模式的通知模式
    • 4,实例
    • 5,观察者模式的优缺点
  • 六:命令模式-封装调用(行为模式)
    • 1,命令设计模式简介
    • 2,命令设计优缺点
    • FQA
  • 七:模板方法模式-封装算法(行为模式)
    • 1,了解模板方法模式
    • 2,模板方法模式的demo
    • 3,现实世界中的模板方法模式
    • 4,模板方法模式-钩子
    • 5,模板方法模式优点和缺点
    • FQA
  • 八:模型-视图-控制器-复合模式
    • 1,模型-视图-控制器模式
    • 2,MVC模式中涉及的主要类
    • 3,模型、视图、控制器
    • 3,现实生活的MVC模式
    • 4,MVC模式的优点
    • FQA
  • 九:状态设计模式(行为模式范畴)
    • 1,理解状态设计模式
    • 2,状态设计模式实现
    • 3,状态设计模式优缺点
    • 4,状态设计模式uml
    • 5,实例
  • 十:反模式
    • 1,理解
    • 2,软件开发反模式
      • 1,**意大利面条式代码**
      • 2,金锤
      • 3,熔岩
      • 4, 复制粘贴式编程
    • 3,软件架构反模式
      • 1,重新发明轮子
      • 2,供应商套牢
      • 3,委员会设计

一:单例设计模式(创建型模式)

1,单例设计模式理解

模式提供了一个机制,确保类有且只有一个特定的类型的对象,并提供全局的访问点。
用途:
通常用于日志记录、数据库操作、打印后后台处理

2,利用python实现经典的单例模式

# 饿汉式:饿汉式在创建的时候就会生成实例
class SingleTon(object):def __new__(cls):if not hasattr(cls,'instance'):cls.instance = super(SingleTon,cls).__new__(cls)return cls.instanceS = SingleTon()
print("S--",S)
S1 = SingleTon()
print("S1--",S1)
1,重写new,通过hasattr 判断是否已存在这样的实例,存在返回相同的地址
不存在重新建立新的地址
........................................
S-- <__main__.SingleTon object at 0x000002811A2CD0B8>
S1-- <__main__.SingleTon object at 0x000002811A2CD0B8>

3, 懒汉式实例化

代码中有时候创建用不到的对象,懒汉式实例化就是确保我们需要他时候才被创建。
懒汉实例化是一种节约资源并在需要时才创建的他的方式。

# 懒汉式class Singleton(object):__instance = Nonedef __init__(self):if not self.__instance:print('调用__init__, 实例未创建')else:print('调用__init__,实例已经创建过了:', self.get_instance)@classmethoddef get_instance(cls):# 调用get_instance类方法的时候才会生成Singleton实例if not cls.__instance:cls.__instance = Singleton()return cls.__instance
S = Singleton()
print('object created ',Singleton.get_instance())
s1 = Singleton()
.....................................................
调用__init__, 实例未创建
调用__init__, 实例未创建
object created  <__main__.Singleton object at 0x000001D695123F60>
调用__init__,实例已经创建过了: <bound method Singleton.get_instance of <class '__main__.Singleton'>>

4,模块级别的单例模式

默认情况下,模块的都是单例模式,由python导入模式所限制的
通过下方式工作。
1,检查模块是否导入,如已经导入,则返回该模块对象,如果没导入,则导入并实例化
2,因此当模块导入时,会被初始化,当模块被再次导入时,他不会被再次初始化,因为模块只能有一个对象,他返回的是同一个对象。

5,Monostate 单例模式

常程序员需要的是让实例共享相同的状态,该所有对象共享相同的状态,被称为Monostate(单态)模式

#将变量__shared_state赋给__dict__(python用__dict__存储一个类所有对象的状态),这样,这个类创建的所有实例都通过__shared_state共享状态
class Borg:__shared_state = {'1': '2'}def __init__(self):self.x = 1self.__dict__ = self.__shared_statepass
if __name__ == '__main__':b = Borg()b1 = Borg()b.x = 4print('Borg Object "b": ', b)  #不同的实例,print('Borg Object "b1": ', b1)print('Object State "b": ', b.__dict__)  # 相同的状态print('Objcet State "b1": ', b1.__dict__)....................................................
Borg Object "b":  <__main__.Borg object at 0x0000019419F13F60>
Borg Object "b1":  <__main__.Borg object at 0x0000019419F2D0F0>
Object State "b":  {'1': '2', 'x': 4}
Objcet State "b1":  {'1': '2', 'x': 4}

另一种方式是通过重写__new__方法来实现

class Borg(object):__shared_state = {}def __new__(cls, *args, **kargs):obj = super(Borg, cls).__new__(cls, *args, **kargs)obj.__dict__ = cls.__shared_statereturn objdef __init__(self):self.x = 1
if __name__ == '__main__':b = Borg()b1 = Borg()b.x = 4print('Borg Object "b": ', b)  print('Borg Object "b1": ', b1)print('Object State "b": ', b.__dict__)  print('Objcet State "b1": ', b1.__dict__)

元类:是一个类的类;意味着该类是他元类的实例,从预定义的python类创建自己类型的类。实例对象是由类来创建,那么类又是由什么来创建的呢? 答案就是元类。

6,单例模式缺点

全局变量可能在拿点被修改,开发人员可能不知道,但还在某处使用。
可能对同一个对象创建多个引用,由于单例只创建一个对象,因此这种情况下会对同一个对象创建多个引用。
所有依赖全局变量的类都会由于一个类的改变而紧密耦合成全局数据,从而在无形中影响类一个类;

7,单例模式demo

为基础设施提供运行状态监控服务,定义服务列表信息,可以检测新增设备,可以检测删除设备,第二次迭代式,返回时修改后的信息。

class HealthCheck:_instance = Nonedef __new__(cls, *args, **kwargs):if not HealthCheck._instance:HealthCheck._instance = super(HealthCheck,cls).__new__(cls,*args,**kwargs)return HealthCheck._instancedef __init__(self):self._servers = []def addServer(self):self._servers.append("Server 1")self._servers.append("Server 2")self._servers.append("Server 3")self._servers.append("Server 4")def changServer(self):self._servers.pop()self._servers.append("Server 6")
hc1 = HealthCheck()
hc2 = HealthCheck()
hc1.addServer()
for i in range(4):print(hc1._servers[i])
hc2.changServer()
print('&'.ljust(90,'&'))
for i in range(5):print(hc2._servers[i])

二:工厂模式-建立创建对象的工厂

1,了解工厂模式

表示负责创建其他类型的对象的类。客户端调用此方法,工厂会依据创建所需要的对象,然后返回给客户端;

优点:
松耦合,对象的创建可以独立于类的实现;
客户端无需了解创建对象的类,可直接调用创建。即它只需要知道接口,方法、参数就能创建对象;
可以轻松的在工厂中调价其他类创建所需要的类型对象,、;
工厂可以重用现有的对象,注意客户端,创建对象,是创建成新的对象;

factory模式分类:
简单工厂模式:允许接口创建对象,但不会暴漏创建的逻辑;
工厂方法模式:允许接口创建对象,但使用那个类来创建由他的子类来决定的;
抽象工厂模式:能够创建一系列相关的对象,而无需指定/公开其具体的接口,该模式能够提供其他工厂的对象,在其内部创建其他对象;

2,简单工厂模式

简单工厂模式(Simple Factory Pattern):是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类

简单工厂模式结构

from abc import ABCMeta,abstractmethodclass Animal(metaclass=ABCMeta): # 同一类事物
##上述代码子类是约定俗称的实现这个方法,加上@abc.abstractmethod装饰器后严格控制子类必须实现这个方法@abstractmethoddef do_say(self):pass
class Dog(Animal):def do_say(self):print('dog')
class Cat(Animal):def do_say(self):print('cat')
class ForestFactory(object):def make_sound(self,object_type):return  eval(object_type)().do_say() #val是Python的一个内置函数,这个函数的作用是,返回传入字符串的表达式的结果。即变量赋值时,等号右边的表示是写成字符串的格式,返回值就是这个表达式的结果
if __name__ == '__main__':ff = ForestFactory()animals = input('Dog or Cat:')ff.make_sound(animals).............................................
Dog or Cat:Cat
cat

3,工厂方法模式

我们定义了一个接口来创建对象,但工厂本身并不负责创建对象,而是将这任务交给子类来完成,即子类来决定要实例化哪些类。
factory方法的创建是通过继承而不是通过实例化来完成的。
工厂方法使设计更加的具有可定制性,他可以返回相同的实例或子类,而不是某些类型的对象

1,实现工厂方法

工厂方法实现放在factory_method.py模块中

class BenBen:def __init__(self, money):"""奔奔支付:param money:支付金额"""self.money = moneydef pay(self):print("收到奔奔金融支付金额{0}".format(self.money))class WeChat:def __init__(self, money):"""微信支付:param money:支付金额"""self.money = moneydef pay(self):print("收到微信支付金额{0}".format(self.money))class ZhiFuBao:def __init__(self, money):"""支付宝支付:param money:支付金额"""self.money = moneydef pay(self):print("收到支付宝支付金额{0}".format(self.money))class BenBenFactory:def create(self, money):"""奔奔支付工厂:param money:支付金额:return:"""return BenBen(money)class ZhiFuBaoFactory:def create(self, money):"""支付宝支付工厂:param money:支付金额:return:"""return ZhiFuBao(money)class WeChatFactory:def create(self, money):"""微信支付工厂:param money:支付金额:return:"""return WeChat(money)

调用工厂方法

from factory_method import BenBenFactory, WeChatFactory, ZhiFuBaoFactoryfacotry = BenBenFactory()
benben = facotry.create(100)
benben.pay()facotry = WeChatFactory()
we_chat = facotry.create(200)
we_chat.pay()
facotry = ZhiFuBaoFactory()
zhi_fu_bao = facotry.create(300)
zhi_fu_bao.pay()
..............................................收到奔奔金融支付金额100
收到微信支付金额200
收到支付宝支付金额300

2,工厂方法模式的优点

具有更大的灵活性、通用性,因为他不在是单纯的实例化某个类,实现哪些类取决于接口
松耦合,因为创建对象的代码与使用对象的代码是分开的。客户端完全不需要关心传递了哪些参数以及实例化哪些类
由于添加类更加容易,降低了维护的成本。

4,抽象工厂模式

主要目的:提供一个接口创建一系列相关对象,而无需指定具体的类。
工厂方法模式把创建实例的任务给了子类,
抽象工厂的方法的目标:创建一系列相关对象。

实际上抽象工厂模式不仅确保客户端与对象的创建相互隔离,还确保客户端能够使用创建的对象;但客户端只能通过接口访问对象,如果使用一系列中的多个对象,那么抽象工厂模式能够帮助客户端一次使用来自一个产品的多个对象。

1,实现抽象工厂模式

# -*-coding:utf-8 -*-
__author__ = 'Andy'
import sys#抽象用户表类
class User(object):def get_user(self):passdef insert_user(self):pass
#抽象部门表类
class Department(object):def get_department(self):passdef insert_department(self):pass
#操作具体User数据库类-Mysql
class MysqlUser(User):def get_user(self):print('MysqlUser get User')def insert_user(self):print( 'MysqlUser insert User')
#操作具体Department数据库类-Mysql
class MysqlDepartment(Department):def get_department(self):print('MysqlDepartment get department')def insert_department(self):print( 'MysqlDepartment insert department')
#操作具体User数据库-Orcal
class OrcaleUser(User):def get_user(self):print( 'OrcalUser get User')def insert_user(self):print( 'OrcalUser insert User')
#操作具体Department数据库类-Orcal
class OrcaleDepartment(Department):def get_department(self):print( 'OrcalDepartment get department')def insert_department(self):print( 'OrcalDepartment insert department')
#抽象工厂类
class AbstractFactory(object):def create_user(self):passdef create_department(self):pass
class MysqlFactory(AbstractFactory):def create_user(self):return MysqlUser()def create_department(self):return MysqlDepartment()
class OrcaleFactory(AbstractFactory):def create_user(self):return OrcaleUser(User)def create_department(self):return OrcaleDepartment(Department)
if __name__ == "__main__":db = sys.argv[1]myfactory = ''if db == 'Mysql':myfactory = MysqlFactory()elif db == 'Orcal':myfactory = OrcaleFactory()else:print("不支持的数据库类型")exit(0)user = myfactory.create_user()department = myfactory.create_department()user.insert_user()user.get_user()department.insert_department()department.get_department()

类的设计如下图:

2,工厂方法与抽象工厂

工厂方法 抽象工厂
他向客户端开放一个创建对象的方法 它包含一个或者多个工厂方法来创建一系列的相关对象
他使用继承和子类来创建哪个对象 它使用组合将创建对象的任务委托给了其他类
用于创建一个产品 用于创建相关产品的系列

三:门面模式-与门面相适(结构型模式)

1,理解结构型设计模式

结构型模式:
a:描述如何将对象和类组合成更大的结构;
b:一种能够简化设计工作的模式,因为他能够找出更简单的方法来认识或者表示实体间的关系。面向对象世界中,实体是指对象或者类;
c:类模式可以通过继承来描述抽象,从而提供更有用的程序接口,而对象模式则是描述如何将对象联系起来从而组合成更大的对象。结构型模式是类和对象模式的综合体;

结构型设计模式例子:
他是通过对象或类之间的交互来实现更高级的设计或架构目标。
适配器模式:将一个接口转换成客户希望的另外一个接口;他试图根据客户端需求匹配不同类的接口;
桥接模式:该模式将对象的接口与其实现进行解耦;使得俩者可以独立工作;
装饰器模式:允许在运行时候或以动态方式为对象添加职责;我们可以通过接口给对象添加属性。

2,理解门面设计模式

门面通常是指建筑物的表面,尤其事最有吸引力的那一面。但外面人却不了解内部的复杂性,这就是门面模式使用方法。
门面模式完成事情:
他为子系统的接口提供了统一的接口,并定义了一个高级的接口来帮助客户端通过更加简单的方式使用子系统。
解决的问题是,如何用单个接口对象来表示复杂的子系统。实际上他并不是封装子系统,而是对底层子系统进行组合;
促进实现与多个客户端的解耦;

3,门面设计模式-UML


这里面有三个参与者,门面,客户端,系统
门面:门面接到客户端的请求,去判断该由哪些子系统完成工作,并且安排给他们任务。
他是一个接口,知道请求是由哪个子系统进行处理;
他是一个组合将客户端的请求委派给相应的子系统对象;
系统:系统处理门面对象分配的任务,完成工作
它实现子系统的功能,同时由一个类表示,理想下,是由一组负责不同任务的类组成;
客户端:客户端实例化门面类,并向门面提出要求,去让子系统完成相应的功能
他是实例化门面得类
为了让子系统完成相应的工作,客户端需要向门面提出请求;

4,门面模式的实现

class Client():def order(self):Waiter().make_set_meal_1()class Waiter():def make_set_meal_1(self):Coke().make()Hamburger().make()French_fries().make()class Coke():def make(self):print('making coke')class Hamburger():def make(self):print('making hamburger')class French_fries():def make(self):print('making french fries')you=Client()
you.order()
...................................
making coke
making hamburger也不需要修改子aking french fries
.................................................
order 内的Waiter().make_set_meal_1() 是套餐,也可以在waiter添加组合,也不需要修改子类信息

5,最少知识原则

门面不仅为我们提供了统一的系统,使子类更加易用,客户端与系统的解耦;而门面背后的设计原则就是最少知识原则
最少知识原则知道我们减少对象之间的交互:
意味着:
设计系统时,对于创建的每个对象,都应该考察与之交互的数量,以及交互的方式;
遵循这个原则,能够避免创建许多彼此紧密耦合的类的情况;
如果类之间存在大量的依赖关系,那么系统会变得难以维护,系统内部改动的话,可能导致其他部分的无意改变,这意味着系统的退化。

FQA:
1,迪米特原则是什么?他与工厂模式有何关系?
迪米特是一种设计原则:
每个单元对系统其他单元知道的越少越好,
单位应该之与其朋友交流;
单元不应该知道他操作对象的内部细节;
最少知识原则和迪米特原则一致,都是指向松耦合理论。最少知识原则适用于门面模式的用例,并且原则是指导方针 的意思,而不是严格遵守;

四:代理模式-控制对象的方法

1,理解代理设计模式

代理通常就是介于寻求与提供方之间的中介系统。寻求方是发送请求的一方,而提供方是根据请求提供资源的一方。

在web中,它相当于代理服务器,客户端向网站发送请求时,首先连接到代理服务器,然后向它请求诸类网页资源。代理服务器在内部评估,并发送到适应的服务器,当他收到请求时,就会返回给客户端。
因此,代理服务器可以封装请求,保护隐私,并且非常适合在分布式架构中运行;

代理模式应用场景:
a:能够以更简单的方式表达一个复杂系统的系统。例:涉及多个复杂计算或过程时,系统应提供简单接口
b:提高实际对象的安全性;许多情况下,都不允许客户端直接访问实际对象,为防止恶意危害,代理可以起到保护作用,从而保护实际对象;
c:为不同服务器上的远程提供本地接口。客户端希望在远程系统上运行某些命令的分布式系统,客户端没这个权限实现这一点,因此需要交给本地代理对象执行;
d:他为消耗大量内存的对象提供轻量级的句柄;有时非必要情况,不想加载主要对象,例:在网站用户个人简介内,最好是在页面显示简介头像的缩略图,当展示详细介绍可以加载实际图片;

代理模式优点
a:可以通过缓存笨重的对象或频繁访问对象来提高应用程序的性能;
b:提供了对真实主题的访问权限;只有委派合适权限,代理模式才会接受委派;
c:远程代理还便于与可用网络和数据连接的远程服务器进行交互,并可用于监视系统;

2,代理模式的uml


参与者:
**代理:**它维护一个引用,允许(proxy代理)这个引用来访问实际对象。它虽然提供一个与主题相同的接口,以便可以替代真实的主题。代理还负责创建和删除主题。
主题:定义了realsubject 与proxy的工共接口。以他两个形式实现主题;使用realsubject 的任何地方都可以使用代理(proxy)。
真实主题:他定义了代理所代表的真实主题;

3,不同类型的代理

**1.远程代理,**也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。

2.虚拟代理,是根据需要创建开销大的对象。通过它来存放实例化需要很长时间的真是对象,例如html中,图片需要load很久,所以通过虚拟代理来代替真实的图片

3.安全代理,用来控制真实对象访问时的权限

4.智能代理,是指当调用真实的对象时,代理处理另外一些事

4,代理模式demo

class Cache(object):"""use for save source that ofen is requested"""def __init__(self):self.cache = {}def get(self, key):return self.cache.get(key)def set(self, key, value):self.cache[key] = valueprint('set %s to %s' % (value, key))cache = Cache()class Souce(object):def __init__(self, name):self.name = name@propertydef obtain(self):print('get source from source')return 'source of %s' % self.nameclass Source_proxy(object):def __init__(self, source):self.source = source@propertydef obtain(self):content = cache.get(self.source.name)if not content:content = self.source.obtaincache.set(self.source.name, content)else:print('get source from cache')return contentclass Client(object):def __init__(self, source):self.source = sourcedef show(self):print('from backend get source %s' % self.source.obtain)if __name__ == '__main__':source = Souce('picture.jpg')proxy = Source_proxy(source)# first visitclient = Client(proxy)client.show()# second visitprint('*' * 20)client.show()...............................get source from source
set source of picture.jpg to picture.jpg
from backend get source source of picture.jpg
********************
get source from cache
from backend get source source of picture.jpg

5,门模式与代理模式比较

代理模式 门面模式
他为其他对象提供了占位符或代理,以控制对原始对象的访问 他为类的大型子系统提供了一个接口
代理对象与目标对象具有相同的接口,并保存有目标对像的引用 实现了子系统间的通信与依赖性的最小化
充当客户端与被封装的对象之间的中介 面对对象提供了单一的简单接口

FQA:
Q1.装饰器模式与代理模式有啥区别?
装饰器向在运行时装饰的对象添加行为,而代理模式则是控制对象的访问。代理和真实主体间的关联是在编译时完成的,而不是动态的

Q2.代理模式的缺点?
代理模式会增加响应时间;例:如果没有良好的体系结构或性能,他会增加真实主题的相应时间。一般取决于代码写得多好。

Q3.客户端可以直接访问真实主题么?
可以,但代理模式能够提供许多优势,例如,虚拟机、远程等,所以使用代理模式会更好些。

Q4.代理是否能够给自己添加任何功能?
代理可以向主题添加额外的功能,而无需更改对象的代码。代理和真实主题可以实现相同的接口。

五:观察者模式-了解对象的情况(行为模式)

三种模式的简介:
https://blog.csdn.net/weixin_42914706/article/details/116106480

1,理解观察者设计模式

观察者设计模式中,对象主题维护了一个依赖观察者的列表,以便主题可以使用观察者定义的任何方法通知所有观察者他发生的变化。
在分布式应用中,多个服务通常都是彼此交互来实现用户想要实现的更大型的操作。服务可以执行多种操作,但是他们的操作执行会直接或很大程度上取决于与其交互的服务对象的状态。


Observer为观察者定义了一个接口,里边定义了观察者获得通知的方法,ConcreteObserver(具体观察者)实现这些接口,并与主题创建相关联系,Subject主题存储所有注册的观察者,并向所有观察者发送新消息。

这个模式有3个主要角色:

主题(Subject):类Subject需要了解Observer。Subject类具有许多方法,诸如register( )和deregister( )等,Observer可以通过这些方法注册到Subject类中。因此,一个Subject可以处理多个Observer。
观察者(Observer):它为关注主题的对象定义了一个接口。它定义了Observer需要实现的各个方法,以便在主题发生变化时能够获得相应的通知。
具体观察者(ConcreteObserver):它用来保存应该与Subject的状态保持一致的状态。它实现了Observer接口以保持其状态与主题中的变化相一致。
这个流程非常简单。具体观察者通过实现观察者提供的接口向主题注册自己。每当状态发生变化时,该主题都会使用观察者提供的通知方法来通告所有具体观察者。

3,观察者模式demo

class Subject:def __init__(self):self.__observers = []def register(self, observer):self.__observers.append(observer)def notifyAll(self, *args, **kwargs):for observer in self.__observers:observer.notify(self, *args, **kwargs)class Observer1:def __init__(self, subject):subject.register(self)def notify(self, subject, *args):print(type(self).__name__, "::Got", args, "From", subject)class Observer2:def __init__(self, subject):subject.register(self)def notify(self, subject, *args):print(type(self).__name__, "::Got", args, "From", subject)subject = Subject()
objserver1 = Observer1(subject)
objserver2 = Observer2(subject)
subject.notifyAll("notification")
..................................
Connected to pydev debugger (build 191.6605.12)
Observer1 ::Got ('notification',) From <__main__.Subject object at 0x0000029F32485F28>
Observer2 ::Got ('notification',) From <__main__.Subject object at 0x0000029F32485F28>

3,观察者模式的通知模式

有两种不同的方式可以通知观察者在主题中发送的变化。他们可以被分为推模型或拉模型。

a:拉模型
在拉模型中,观察者扮演积极的角色。

每当发送变化时,主题都会向所有已注册的观察者进行广播。
出现变化时,观察者负责获取相应的变化情况,或者从订户那里拉取数据。
拉模型的效率较低,因为它涉及两个步骤,第一步,主题通知观察者,第二步,观察者从主题那里提取所需的数据。

b:推模型
在推模型中,主题是起主导作用的一方。

与拉模型不同,变化是由主题推送到观察者的。
在拉模型中,主题可以向观察者发送详细的信息(即使可能不需要)。当主题发送大量观察者用不到的数据时,会使响应时间过长。
由于只从主题发送所需的数据,所以能够提高性能。

4,实例

现实世界中的观察者模式;
以新闻机构为例来展示观察者模式的现实世界场景。新闻机构通常从不同地点收集新闻,并将其发布给订阅者。

由于信息是实时发送或接收的,所以新闻机构应该尽快向其订户公布该消息。此外,随着技术的进步,订户不仅可以订阅报纸,而且可以通过其他的形式进行订阅,例如电子邮件、移动设备、短信或语音呼叫。所以,我们还应该具备在将来添加任意其他订阅形式的能力,以便为未来的新技术做好准备。

""
主题的行为由NewsPublisher类表示;
NewsPublisher提供了一个供订户使用的接口;
attach( )方法供观察者(Observer) 来注册NewsPublisherObserver,detach()方法用于注销;
subscriber( )方法返回已经使用Subject注册的所有订户的列表;
notifySubscriber( )方法可以用来遍历已向NewsPublisher注册的所有订户;
发布者可以使用addNews( )方法创建新消息,getNews( )用于返回最新消息,并通知观察者。
"""class NewsPublisher:def __init__(self):self.__subscribers = []self.__latesNews = Nonedef attach(self, subscriber):self.__subscribers.append(subscriber)def detach(self):return self.__subscribers.pop()def subscribers(self):return [type(x).__name__ for x in self.__subscribers]def notifySubscribers(self):for sub in self.__subscribers:sub.update()def addNews(self, news):self.__latesNews = newsdef getNews(self):return "Got News:", self.__latesNewsfrom abc import ABCMeta, abstractmethod"""
Subscriber表示Observer,它是一个抽象的基类,代表其他ConcreteObserver;
Subscriber有一个update( )方法,但是它需要由ConcreteObservers实现;
Subscriber有一个update( )方法,但是它需要由ConcreteObservers实现;update( )方法是由ConcreteObserver实现的,这样只要有新闻发布的时候,它们都能得到Subject``(NewsPublishers)的相应通知。
"""class Subscriber(metaclass=ABCMeta):@abstractmethoddef update(self):pass"""
有两个主要观察者,分别是实现订户接口的EmailSubscriber和SMSSubscriber;
除了这两个之外,我们建立了另一个观察者AnyOtherObserver,它是用来演示Observers与Subject的松散耦合关系的;
每个具体观察者的__init __( )方法都是使用attach()方法向NewsPublisher进行注册的;
具体观察者的update( )方法由NewsPublisher在内部用来通知添加了新的新闻。
"""
class SMSSubscriber(Subscriber):def __init__(self, publilsher):self.publisher = publilsherself.publisher.attach(self)def update(self):print(type(self).__name__, self.publisher.getNews())class EmailSubscriber(Subscriber):def __init__(self, publisher):self.publisher = publisherself.publisher.attach(self)def update(self):print(type(self).__name__, self.publisher.getNews())class AnyOtherSubscriber(Subscriber):def __init__(self, publisher):self.publisher = publisherself.publisher.attach(self)def update(self):print(type(self).__name__, self.publisher.getNews())
"""
所需的订户都已经实现好了,下面让我们来考察NewsPublisher和SMSSubscribers类。
客户端为NewsPublisher创建一个对象,以供具体观察者用于各种操作。
使用发布者的对象初始化SMSSubscriber、EmailSubscriber和AnyOther Subscriber类。
在Python中,当我们创建对象时,__init __( )方法就会被调用。在ConcreteObserver类中,__init __( )方法在内部使用NewsPublisher的attach( )方法进行注册以获取新闻更新。
然后,我们打印出已经通过主题注册的所有订户(具体观察者)的列表。
接着,使用newsPublisher(news_publisher)的对象通过addNews( )方法创建新消息。NewsPublisher的notifySubscribers( )方法用于通知所有订户出现了新消息。notifySubscribers( )方法在内部调用由具体观察者实现的update()方法,以便它们可以获得最新的消息。NewsPublisher还提供了detach( )方法,可从注册订户列表中删除订户。
"""
if __name__ == "__main__":news_publisher = NewsPublisher()for Subscribers in [SMSSubscriber, EmailSubscriber, AnyOtherSubscriber]:Subscribers(news_publisher)print("\nSubscribers:", news_publisher.subscribers())news_publisher.addNews("Hello World!")news_publisher.notifySubscribers()print("\nDetached:", type(news_publisher.detach()).__name__)print("\nSubscribers:", news_publisher.subscribers())news_publisher.addNews("My second news!")news_publisher.notifySubscribers()
......................................
Subscribers: ['SMSSubscriber', 'EmailSubscriber', 'AnyOtherSubscriber']
SMSSubscriber ('Got News:', 'Hello World!')
EmailSubscriber ('Got News:', 'Hello World!')
AnyOtherSubscriber ('Got News:', 'Hello World!')Detached: AnyOtherSubscriber

5,观察者模式的优缺点

优点:

它使得彼此交互的对象之间保持松耦合。
它使得我们可以在无需对主题或观察者进行任何修改的情况下高效地发送数据到其他对象。
可以随时添加/删除观察者。
缺点:

观察者接口必须有具体观察者实现,而这涉及继承。无法进行组合,因为观察者接口可以实例化。
如果实现不当的话,观察者可能会增加复杂性,并导致性能降低。
在软件应用程序中,通知有时可能是不可靠的,并导致竞争条件或不一致性。

FQA:
a:可能存在多个主题和观察者吗?
当一个软件应用程序建立了多个主题和观察者的时候,是可能的。在这种情况下,要想正常工作,需要通知观察者哪

b:谁负责触发更新?
观察者模式可以在推模型和拉模型中工作。通常情况下,当发生更新时,主题会触发更新方法,但有时可以根据应用程序的需要,观察者也是可以触发通知的。然而,需要注意的是频率不应该太高,否则可能导致性能下降,特别是当主题的更新不太频繁时。

c:主题或观察者可以在任何其他用例中访问吗?
是的,这就是松散耦合的力量在观察者模式中的强大体现。主题和观察者是可以独立使用的。

六:命令模式-封装调用(行为模式)

1,命令设计模式简介

命令模式的定义为:将一个请求封装成一个对象,从而可以使用不同的请求将客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。命令模式中通常涉及三类对象的抽象:Receiver,Command,Invoker(本例中的waiterSys)。

由uml发现:
command :声明执行操作的接口;command 了解receiver 对象的情况,并能调用receiver对象的方法;
concretecommand:将receiver 对象和一个操作绑定在一起;
client:创建concretecommand对象并设定其接收者;
invoker:要求concretecommand执行这个请求;
receiver:调用者知道如何执行命令;

# 命令类
class Command(object):def __init__(self, receiver):self.receiver = receiverdef execute(self):pass
# 执行接收者的操作
class ConcreteCommand(Command):def execute(self):self.receiver.action()
# 具体执行类
class Receiver(object):def action(self):print( "执行请求")
# 接收命令
class Invoker(object):def __init__(self):self.command = ''def setcommand(self,command):self.command = commanddef excutecommand(self):self.command.execute()if __name__ == "__main__":r = Receiver() #创建需要执行的命令c = ConcreteCommand(r) # 绑定要执行的命令i = Invoker() # 创建命令执行者i.setcommand(c) # 接受命令i.excutecommand() # 执行命令........执行请求

command 、receiver、invoker、与client
command 了解receiver 对象的情况,并能调用receiver对象的方法;
调用者方法的参数值存储在command对象中;
调用者知道如何执行命令;
客户端用来创建command对象并设置其接收者;

命令模式主要意图:
将请求封装为对象;
可用不同的请求对客户端进行参数化;
允许将请求保留在列队中;
提供面向对象的回调;
命令模式用于场景;
根据需要执行的操作对对象进行参数化;
将操作添加列队并在不同地点执行请求;
创建一个结构根据较小的操作来完成高级操作;

2,命令设计优缺点

优点:
a:低耦合:调用者和接收者之间没有什么直接关系,二者通过命令中的execute接口联系;
b:扩展性好:新命令很容易加入,也很容易拼出“组a:合命令”。
应用场景:
a:触发-反馈机制的系统,都可以使用命令模式思想。如基于管道结构的命令系统(如SHELL),可以直接套用命令模式;此外,GUI系统中的操作反馈(如点击、键入等),也可以使用命令模式思想。
缺点:
a:如果业务场景中命令比较多,那么对应命令类和命令对象的数量也会增加,这样系统会膨胀得很大。

FQA

Q1,命令模式中是否可以不实现reciver与concretecommand?
可以,许多软件就是通过这种方式来使用命令模式的,这里唯一要注意的调用者与接收者之间的交互。如果接收者未被定义的话,则去耦程度就会下降,此时参数化的优势就不复存在,
Q2,我使用是么模式数据结构来实现INvoker对象中的列队机制?
命令模式可以使用一个堆栈来实现列队机制,这在开发具有重做或回滚功能的时候非常有帮助;

七:模板方法模式-封装算法(行为模式)

1,了解模板方法模式

模板方法模式:
定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定的步骤。子类实现的具体方法叫作基本方法,实现对基本方法高度的框架方法
模板方法模式应用场景:
a:当多个算法和类实现类似或相同逻辑的时候;
b:子类实现算法有助于减少代码的复用
c:可以用子类实现覆盖实现的行为来定义多个算法的时候;

模板方法模式的主要意图:
使用基本操作定义算法的框架;
重新定义某些子类的某些操作,而无需修改算法的结构;
实现代码的重用并避免重复工作;
利用通用接口或实现;

模板方法UML类图

模板方法模式术语:
1 AbstractClass : 声明一个算法步骤的接口。
2 tmplate_method():通过调用步骤方法来定义算法;
3 ConcreteClass:定义子类特定的步骤;

2,模板方法模式的demo

from abc import ABCMeta, abstractmethod# 抽象方法 AbstractClass
class AbstractClass():def __init__(self):pass@abstractmethoddef operation1(self):pass@abstractmethoddef operation2(self):pass#  模板方法 tmplate_method()def template_method(self):print("Defining the Algorithm.Operation1 follows Operation2")self.operation2()self.operation1()
# 具体类 ConcreteClass
class ConcreteClass(AbstractClass):def operation1(self):print("My Concrete Operation1")def operation2(self):print("Operation 2 remains same")
# 客户端
class Client:def mian(self):self.concreate = ConcreteClass()self.concreate.template_method()
client = Client()
client.mian().................................................
Defining the Algorithm.Operation1 follows Operation2
Operation 2 remains same
My Concrete Operation1

3,现实世界中的模板方法模式

from abc import ABCMeta, abstractmethod# 抽象方法 Trip
class Trip():def __init__(self):pass@abstractmethoddef setTransport(self):pass@abstractmethoddef day1(self):pass@abstractmethoddef day2(self):pass@abstractmethoddef day3(self):pass@abstractmethoddef returnHome(self):pass#  模板方法 tmplate_method()def itinerary(self):self.setTransport()self.day1()self.day2()self.day3()self.returnHome()
# 具体类 VeniceTrip
class VeniceTrip(Trip):def setTransport(self):print("Take a boat and find your way in the Grand Canal")def day1(self):print("Visit St Mark Basilica in St Mark Square")def day2(self):print("Enjoy the food near the Rialto Bridge")def day3(self):print("Get souvenirs for friends and get back")def returnHome(self):print("Get souvenirs for friends and get back")# 具体类 MaldivesTrip
class MaldivesTrip(Trip):def setTransport(self):print("On foot,on any island,Wow")def day1(self):print("Enjoy the marine life of Banana Reef")def day2(self):print("Go for the water sports and snorkelling")def day3(self):print("Relax on the beach and enjoy the sun")def returnHome(self):print("Dont feel like leaving the beach..")
# 客户端
class TravelAgency:def arrange_trip(self):choice = input("What kind of place you like to go historical or to a beach")if choice == "historical":self.trip = VeniceTrip()self.trip.itinerary()if choice == "beach":self.trip = MaldivesTrip()self.trip.itinerary()
TravelAgency().arrange_trip()
...........
What kind of place you like to go historical or to a beach
【historical】
.................................................
Take a boat and find your way in the Grand Canal
Visit St Mark Basilica in St Mark Square
Enjoy the food near the Rialto Bridge
Get souvenirs for friends and get back
Get souvenirs for friends and get back

@abstractmethod
用于程序接口的控制,正如上面的特性,含有@abstractmethod修饰的父类不能实例化,但是继承的子类必须实现@abstractmethod装饰的方法

4,模板方法模式-钩子

a:钩子是在抽象类中声明的方法,它通常被赋予一个默认实现
b:常情况下,当子类必须提供实现时,我们会使用抽象方法,并且当子类的实现不是强制的时候,我们就会使用钩子。

5,模板方法模式优点和缺点

优点:
a:代码没有重复
b:模板方法用的继承而非合成,代码可以重用。
c:灵活性允许子类决定如何实现算法中的步骤。
缺点:
a:调试和理解模板方法中的流程序列有时会令人困惑。
c:维护难度大

FQA

a:是否应该禁止底层组件调用更高层组件中的方法
不,底层组件当然通过继承来调用高层组件。然而,程序员需要注意的是,不要出现循环依赖性,即高层组件和底层组件彼此依赖。
b:策略模式是否类似于模板模式?
模板取决于继承,而策略使用组合。模板方法模式是通过子类化在编译时进行算法选择,而策略模式是运行时进行选择

八:模型-视图-控制器-复合模式

以上我们总结了结构型、创建型、行为型设计模式,实际项目中很少使用单一的设计模式,都是模式的组合完成各个功能,即复合模式

1,模型-视图-控制器模式

MVC:
不仅时实现用户界面的软件模式,也是易于维护与修改的架构。

MVC基本部分:
模型、视图、控制器;

MVC工作机制
模型:提供数据与业务逻辑
视图:负责数据的展示
控制器:两者之间的粘合,根据需求呈现方式协调模型和视图;
视图与控制器依赖于模型,主要是因为用户所关心的是数据;模型可以单独工作的,这也是MVC模式关键所在。

MVC设计模式术语:
模型:声明一个储存和操作的数据类;
视图:声明一个类来构建用户界面与试图类;
控制器:声明一个连接模型和视图的类;
客户端:声明一个类,根据某些操作来获取某些结果;

MVC流程:

2,MVC模式中涉及的主要类

a:模型类定义针对数据的所有操作,并提供与数据使用方式有关的方法;
b:视图类代表用户界面。它提供应用的方法,帮助我们根据上下文与应用程序的需要来构建web或GUI界面,不包含自己的任何逻辑,而只应该显示数据。
c:控制器类从请求到接受数据,并将它发送到系统的其他部分。他需要提供用于路由请求的方法。

mvc常用于场景:
当需要更改展示方向而不更改业务逻辑时。
多个控制器可用于使用多个视图来更改用户界面上的展示。

mvc模式意图:
将数据于数据的展示隔离开;
使类的维护与使用更加简单;
灵活的改变数据的存储和显示方式,两者都是独立的,因此可以更加灵活的修改

3,模型、视图、控制器

模型
应用程序的基石,因为它独立于视图和控制器,而视图和控制器则依赖于模型。
还提供客户请求数据,模型由存储与返回信息的数据库来表示。

视图:
视图用来将数据展示在接口上,供查看。它无多余的逻辑和算法,其具体应该放在控制器或者模型中。
视图应该避免与数据库直接交互,应该借助模型来获取所需要的数据;

控制器:

控制用户在界面上的交互,控制器可以将数据传递给视图,以便信息呈现在接口上;

3,现实生活的MVC模式

class Model(object):services = {'email': {'number': 1000, 'price': 2, },'sms': {'number': 1000, 'price': 10, },'voice': {'number': 1000, 'price': 15, },}class View(object):def list_services(self, services):for svc in services:print(svc, '')def list_pricing(self, services):for svc in services:print('For', Model.services[svc]['number'],svc, "message you pay $",Model.services[svc]['price'])class Controller(object):def __init__(self):self.model = Model()self.view = View()def get_services(self):services = self.model.services.keys()return (self.view.list_services(services))def get_pricing(self):services = self.model.services.keys()return (self.view.list_pricing(services))class Client(object):controller = Controller()print("Services Provided:")controller.get_services()print("Services for Services:")controller.get_pricing().................................
Services Provided:
email
sms
voice
Services for Services:
For 1000 email message you pay $ 2
For 1000 sms message you pay $ 10
For 1000 voice message you pay $ 15

4,MVC模式的优点

a:使用MVC模式,开发人员可以将程序分为3个主要部分,模型、视图、控制器,有助于维护、扩展,强制松耦合并降低复杂性;
b:MVC允许对前端进行独立更改,而面对后端逻辑无需任何修改或只需要进行很少的更改,因此开发工作仍可继续进行;
c:类似,更改控制器与视图也对模型影响很小;

FQA

a:MVC是一种模式?为什么称为符合模式?
本质上符合模式就是相互配合共同解决软件应用程序开发中的大型涉及问题的组合模式;通常被视为一个模式;
b:MVC模式只用于网站么?
MVC模式用于多个领域,例如:GUI应用程序或任何松散耦合和需要拆分组件使其保持独立的地方;
c:多个视图可以使用多个模式么?
可以,通常你最终会遇到从多个模型整理数据并在一个视图中显示的情况。

九:状态设计模式(行为模式范畴)

1,理解状态设计模式

行为模式关注的对象的响应性,通过对象之间的交互以实现强大的功能,他是行为模式一种,有时被称为状态模式的对象。
一个对象可以基于其内部状态封装多个行为
也可以看做在运行时改变对象行为的一种方式(Python正好擅长这一点)

状态机是一个抽象机器,具有两个主要部分:状态和转换。状态是指一个系统的当前状况。一个状态机在任意时间点只会有一个激活状态。转换是指从当前状态到一个新状态的切换。在一个转换发生之前或之后通常会执行一个或多个动作。状态机可以使用状态图进行视觉上的展现。

状态机用于解决许多计算机问题和非计算机问题,其中包括交通灯、停车计时器、硬件设计和编程语言解析等。我们也看到零食自动贩卖机是如何与状态机的工作方式相关联的

2,状态设计模式实现

from abc import ABCMeta, abstractmethod
class State(metaclass=ABCMeta):@abstractmethoddef handel(self):pass
class ConcreteStateA(State):def handel(self):print('A')
class ConcreteStateB(State):def handel(self):print('B')
class Context(State):def __init__(self):self.state = Nonedef get_state(self):return self.statedef set_state(self, state):self.state = statedef handel(self):self.state.handel()
context = Context()
sA = ConcreteStateA()
sB = ConcreteStateB()
context.set_state(sA)
context.handel()
........................
A

3,状态设计模式优缺点

优点:
消除了对if/else或者switch的依赖
易于添加状态
提高聚合性
只添加一个ConcreteState类就可以添加行为,提高可维护性

缺点:
类太多了,每个行为都要写类,结构复杂,代码增加
随着新行为(类)的增加,Context都要进行更改,上下文更容易受到新类的影响。

4,状态设计模式uml

5,实例

电梯在我们周边随处可见,电梯的控制逻辑中心是由电梯控制器实现的。电梯的控制逻辑,即使简单点设计,把状态分成开门状态,停止状态和运行状态,操作分成开门、关门、运行、停止,那流程也是很复杂的。首先,开门状态不能开门、运行、停止;停止状态不能关门,停止;运行状态不能开门、关门、运行。要用一个一个if…else…实现,首先代码混乱,不易维护;二是不易扩展

from abc import abstractmethod, ABCMeta# 抽象的状态类
class LiftState(metaclass=ABCMeta):@abstractmethoddef open(self):pass@abstractmethoddef close(self):pass@abstractmethoddef run(self):pass@abstractmethoddef stop(self):passclass OpenState(LiftState):def open(self):print("OPEN:The door is opened...")return selfdef close(self):print("OPEN:The door start to close...")print("OPEN:The door is closed")return StopState()def run(self):print("OPEN:Run Forbidden.")return selfdef stop(self):print("OPEN:Stop Forbidden.")return selfclass RunState(LiftState):def open(self):print("RUN:Open Forbidden.")return selfdef close(self):print("RUN:Close Forbidden.")return selfdef run(self):print("RUN:The lift is running...")return selfdef stop(self):print("RUN:The lift start to stop...")print("RUN:The lift stopped...")return StopState()class StopState(LiftState):def open(self):print("STOP:The door is opening...")print("STOP:The door is opened...")return OpenState()def close(self):print("STOP:Close Forbidden")return selfdef run(self):print("STOP:The lift start to run...")return RunState()def stop(self):print("STOP:The lift is stopped.")return selfclass Context(LiftState):def getState(self):return self._statedef setState(self, state):self._state = statedef open(self):self.setState(self._state.open())def close(self):self.setState(self._state.close())def run(self):self.setState(self._state.run())def stop(self):self.setState(self._state.stop())# 电梯先在STOP状态,然后开门,开门时运行Run,被禁止,然后,关门、运行、停止。
class Client(object):def main(self):ctx = Context()ctx.setState(StopState())ctx.open()ctx.run()ctx.close()ctx.run()ctx.stop()if __name__ == "__main__":Client().main().....................................STOP:The door is opening...
STOP:The door is opened...
OPEN:Run Forbidden.
OPEN:The door start to close...
OPEN:The door is closed
STOP:The lift start to run...
RUN:The lift start to stop...
RUN:The lift stopped...

十:反模式

1,理解

软件设计模式提供了一套规则或标准,能够帮助开发人员在设计层面进行决策。不良的设计主要表现在四个方面:

**不动性:**开发的应用程序非常难以重用
**刚性:**任何小的更改需求都会导致软件的太多部分必须进行相应的改动,牵一发而动全身
脆弱性:应用程序的任何更改都会导致现有系统变得非常容易崩溃
粘滞性:由于架构层面的修改非常困难,修改必须由开发人员在代码层面或环境本身中进行

2,软件开发反模式

软件开发反模式
在软件开发过程中,往往会偏离最初的代码结构,原因一般有:

开发人员的想法会随着开发过程的推进而发生变化
用例通常会随着客户的反馈而进行更改
最初设计的数据结构可能会随功能或可伸缩性等方面的考虑而发生变化
基于上述原因,软件通常需要进行重构

1,意大利面条式代码

典型成因包括:

对面向对象编程和分析的无知
没有考虑产品的架构或设计
快餐式思维
问题:

结构的重用性会降到最低
维护工作量过高
进行修改时,扩展性和灵活性会降低

2,金锤

金锤的意思是一把锤子搞定所有的钉子(解决所有问题)。软件开发人员或团队通常会有一种倾向,一头扎进一个成熟的解决方案,而不管其是否满足适用性
典型成因:

来自不了解具体问题的高层的建议
某解决方案在过去多次验证有效,但当前项目有不同的背景和要求
公司已被这种技术“绑架”,或员工们因为顺手对这种技术情有独钟
金锤的影响

痴迷于一个解决方案,并把它应用于所有软件项目
不是通过功能,而是通过开发中使用的技术来描述产品
没有满足需求,造成与用户的预期不符

3,熔岩

熔岩流与软件应用中的死代码或一段用不到的代码有关,人们害怕一旦对其进行修改就会破坏其他东西。随着时间的流逝,这段代码会一直留在软件中并固化其位置,就像熔岩变成硬岩一样。

熔岩流的成因:

在产品中有大量的试错代码
由一个人单独编写的代码,未经审查的情况下移交给了其他开发团队
软件架构或设计的初始思想是通过代码库实现的,但没有人能理解
熔岩流的症状:

开发的测试工作具有很低的代码覆盖率
代码中含有莫名其妙的注释
过时的接口,或开发人员需要围绕既有代码展开工作

4, 复制粘贴式编程

原因:

新手开发者不习惯编写代码或不知道如何开发
快速修复 bug 或急就章式的开发
代码重复,无法满足跨模块标准化以及代码结构化的要求
缺乏长远打算或深谋远虑
后果:

多个软件应用存在同种类型的问题
维护成本更高,bug 的生命周期也会变得更长
较少的模块化代码库,相同的代码会散落于多处
继承问题

3,软件架构反模式

1,重新发明轮子

原因:

缺乏中央文档或存储库来讲解架构级问题和存放已实现的解决方案
社区或公司内的技术领袖之间缺乏沟通
组织中遵循的流程是从头开始构建的
后果:

解决一个标准问题的方案太多,其中有许多考虑得并不周全
会耗费工程团队更多的时间和资源,导致预算超标,完成时间延后
封闭的系统架构、重复劳动和糟糕的风险管理

2,供应商套牢

原因:

熟悉供应商公司的权威人士以及技术采购的可能折扣
基于营销和销售业务人员而不是技术评估选择的技术
在当前项目中使用经过验证的技术,即使它不适合当前项目的需要
技术人员已经接受过相关技术的培训
后果

公司产品的发布周期和维护周期直接取决于供应商的发布时间
该产品是围绕该技术而不是根据客户的要求开放的
产品上市时间不可靠,不能满足客户的期望

3,委员会设计

原因:

根据组织的流程,产品的架构或设计是由众多的利益相关者批准的
没有指定单独的联系人或负责设计的架构师
由营销或技术专家确定设计优先级,而不是客户反馈
症状:

开发人员和架构师之间的观点冲突,即使在设计完成后依旧如此
过于复杂的设计,很难记录
规格或设计的任何改动都需要经过多次审查,导致实现延迟

python 设计模式-2相关推荐

  1. Python设计模式-装饰器模式

    Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...

  2. Python设计模式-建造者模式

    Python设计模式-建造者模式 代码基于3.5.2,代码如下; #coding:utf-8 #建造者模式 class Burger():name = ""price = 0.0d ...

  3. Python设计模式-状态模式

    Python设计模式-状态模式 代码基于3.5.2,代码如下; #coding:utf-8 #状态模式class state():def writeProgram(self,work):raise N ...

  4. Python设计模式-备忘录模式

    Python设计模式-备忘录模式 代码基于3.5.2,代码如下; #coding:utf-8 #备忘录模式 import randomclass gameCharacter():vitality = ...

  5. Python设计模式-中介者模式

    Python设计模式-中介者模式 代码基于3.5.2,代码如下; #coding:utf-8 #中介者模式class colleague():mediator = Nonedef __init__(s ...

  6. Python设计模式-解释器模式

    Python设计模式-解释器模式 代码基于3.5.2,代码如下; #coding:utf-8 #解释器模式class PlayContext():play_text = Noneclass Expre ...

  7. Python设计模式-职责链模式

    Python设计模式-职责链模式 代码基于3.5.2,代码如下; #coding:utf-8 #职责链模式class Handler():def __init__(self):self.success ...

  8. Python设计模式-命令模式

    Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...

  9. Python设计模式-策略模式

    Python设计模式-策略模式 代码基于3.5.2,代码如下; #coding:utf-8 #策略模式class sendInterface():def send(self,value):raise ...

  10. Python设计模式-外观模式

    Python设计模式-外观模式 代码基于3.5.2,代码如下; #coding:utf-8 # 外观模式class AlarmSensor:def run(self):print("Alar ...

最新文章

  1. Linux内核网络栈1.2.13-socket.c函数概述
  2. Hadoop on Mac with IntelliJ IDEA - 3 解决MRUnit - No applicable class implementing Serialization问题...
  3. 图像检索:几类基于内容的图像分类技术
  4. Codeforces Round #374 (Div. 2) A. One-dimensional Japanese Crosswor 水题
  5. 上传一批动画教程(链接已失效)
  6. 1w用户的并发量多大_QQ邮件订阅中心下线:卢松松博客曾经有1W多订阅用户
  7. 酒店预订、酒店检索、酒店详情、房间预订、订单管理、会员、优惠券、客房预订、高保真原型、酒店app、需求清单、组件规范、架构图、订单通知、服务通知、收藏、客服、搜索、导航、评价、支付、充值、登录、浏览
  8. 吴恩达深度学习神经网络基础编程作业Logistic Regression with a Neural Network mindset
  9. 最简单的基于FFMPEG的图像编码器(YUV编码为JPEG)
  10. python json dump_为什么json.dump()没有以\ n结尾? - python
  11. flash 钟表 钟表代码
  12. java线程定时执行任务_java实现多线程之定时器任务
  13. matlab abort,matlab自动关闭是怎么回事???
  14. 解决systemback 无法生成超过4G的iso的问题
  15. umount target is busy
  16. 大数据下的数据分析平台架构
  17. linux ssh互信配置
  18. Excel成神之道-001-数据分列
  19. Neo4j 图数据库高级应用系列 / 服务器扩展指南 APOC 8.8 - 图生成 完全图
  20. imooc《Python入门与实战》学习总结(七)Python中的面向对象

热门文章

  1. idea 如何新建一个Maven项目并且写第一个servlet
  2. 基于STM32的阿里云物联网项目实战
  3. 系统录音软件哪个好用,怎么录制系统声音
  4. iPhone 屏幕尺寸对于像素点
  5. stata学习笔记#连玉君老师profile.do文件下载设定 #varlist not allowed
  6. java qq2013_Java学习笔记之四——仿作QQ2013登录窗口
  7. cf1900左右的dp
  8. CentOS搭建web服务器,并内网穿透实现公网访问
  9. 天大2021年秋学期考试《土力学与基础工程》离线作业考核试题
  10. angularjs分页