一开始用php做网站,网站开发需要几个人,做网站的分辨率多少,王占山将军是什么军衔Python 设计模式(第2版)
最后介绍下其他设计模式。
模型—视图—控制器#xff08;MVC#xff09;-- 复合模式
根据 GoF 的定义#xff0c;“复合模式将两个或更多模式组合成解决常见或普遍性问题的解决方案”。复合模式不是同时使用的一组模式#xff0c;而是一个问题的…Python 设计模式(第2版)
最后介绍下其他设计模式。
模型—视图—控制器MVC-- 复合模式
根据 GoF 的定义“复合模式将两个或更多模式组合成解决常见或普遍性问题的解决方案”。复合模式不是同时使用的一组模式而是一个问题的通用解决方案。
MVC 不仅是一种实现用户界面的软件模式同时也是一种易于修改和维护的架构。通常来说MVC 模式将应用程序分为3个基本部分模型、视图和控制器。
MVC 模式的工作机制为模型提供数据和业务逻辑如何存储和查询信息视图负责数据的展示如何呈现而控制器是两者之间的粘合剂根据用户要求的呈现方式来协调模型和视图。
MVC 设计模式使用以下术语——模型、视图、控制器和客户端。
模型声明一个存储和操作数据的类。视图声明一个类来构建用户界面和显示数据。控制器声明一个连接模型和视图的类。客户端声明一个类根据某些操作来获得某些结果。
MVC 模式经常用于以下情况。
当需要更改展示方式而不更改业务逻辑时。多个控制器可用于使用多个视图来更改用户界面上的展示。再次重申当模型改变时视图无需改动因为它们是相互独立的。
简而言之MVC 模式的主要意图如下。
将数据和数据的展示隔离开来。使类的维护和实现更加简单。灵活地改变数据的存储和显示方式。两者都是独立的因此可以灵活修改。
为了实现了一个 MVC 设计模式假设我们想要开发一个应用程序告诉用户云公司所提供的营销服务包括电子邮件、短信和语音设施。
首先要开发 model 类模型定义产品提供的服务即电子邮件、短信和语音。然后来定义 view 类视图它提供了将信息反馈给客户端的方法。这些方法是 list_services() 和 list_ pricing()。接下来开始定义 Controller 类这个类定义了两个方法即 get_services() 和 get_pricing()。这两个方法都是用来查询模型并获取数据的然后将数据馈送到视图从而展示给用户。Client 类将实例化控制器然后控制器对象就会根据客户端的请求来调用适当的方法。
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(Pricing for Services:)controller.get_pricing()Client()以下是MVC模式的优点。
使用 MVC开发人员可以将软件应用程序分为 3 个主要部分模型、视图和控制器。这有助于提高可维护性强制松耦合并降低复杂性。MVC 允许对前端进行独立更改而对后端逻辑无需任何修改或只需进行很少的更改因此开发工作仍可以独立运行。类似地可以更改模型或业务逻辑而无需对视图进行任何更改。此外可以更改控制器而不会对视图或模型造成任何影响。MVC 还有助于招聘具有特定能力的人员例如平台工程师和UI工程师他们可以在自己的专业领域独立工作。
状态设计模式 – 状态设计模式
状态模式也属于行为模式的范畴在此模式中一个对象可以基于其内部状态封装多个行为。状态模式也可以看作是在运行时改变对象行为的一种方式。
状态设计模式在 3 个主要参与者的协助下工作。
State这被认为是封装对象行为的接口。这个行为与对象的状态相关联。ConcreteState这是实现 State 接口的子类。ConcreteState 实现与对象的特定状态相关联的实际行为。Context这定义了客户感兴趣的接口。Context 还维护一个 ConcreteState 子类的实例该子类在内部定义了对象的特定状态的实现。
考察一个状态设计模式的真实用例。例如以一个计算机系统台式机/笔记本电脑为例它可以有多个状态如开机、关机、挂起或休眠。想利用状态设计模式来表述这些状态看看如何处理。
首先不妨从 ComputerState 接口开始入手state 应定义两个属性它们是 name 和 allowed。属性 name 表示对象的状态而属性 allowed 是定义允许进入的状态的对象的列表state 必须定义一个 switch() 方法由它来实际改变对象在这种情况下是计算机的状态。
下面来考察实现了 State 接口的 ConcreteState。On这将打开计算机。这时候允许的状态是 Off、Suspend 和 Hibernate。Off这将关闭计算机。这时候允许的状态只有 On。Hibernate该状态将计算机置于休眠模式。当计算机处于这种状态时只能执行打开操作。Suspend该状态将使计算机挂起一旦计算机挂起就可以执行打开操作。
现在来考察 context 类Computer。上下文需要做两个主要的事情__init__()该方法定义了计算机的基本状态。change()该方法将更改对象的状态但是行为的实际更改是由 ConcreteState 类实现on、off、suspend 和 hibernate的。
class ComputerState(object):name stateallowed []def switch(self, state):if state.name in self.allowed:print(Current:, self, switched to new state, state.name)self. __class__ stateelse:print(Current:, self, switching to, state.name, not possible.)def __str__(self):return self.nameclass Off(ComputerState):name offallowed [on]class On(ComputerState):name onallowed [off, suspend, hibernate]class Suspend(ComputerState):name suspendallowed [on]class Hibernate(ComputerState):name hibernateallowed [on]class Computer(object):def __init__(self, modelHP):self.model modelself.state Off()def change(self, state):self.state.switch(state)if __name__ __main__:comp Computer()# Switch oncomp.change(On)# Switch offcomp.change(Off)# Switch on againcomp.change(On)# Suspendcomp.change(Suspend)# Try to hibernate - cannot!comp.change(Hibernate)# switch on backcomp.change(On)# Finally offcomp.change(Off)下面是状态设计模式的优点。
在状态设计模式中对象的行为是其状态的函数结果并且行为在运行时根据状态而改变。这消除了对 if/else 或 switch/case 条件逻辑的依赖。例如在电视远程遥控的场景中我们还可以通过简单地写一个类和方法来实现相应的行为但是该类和方法将用到参数并使用 if/else 语句块来执行具体操作打开/关闭电视。使用状态模式实现多态行为的好处是显而易见的并且更易于添加状态来支持额外的行为。状态设计模式还提高了聚合性因为特定于状态的行为被聚合到 ConcreteState 类中并且放置在代码中的同一个地方。使用状态设计模式通过只添加一个 ConcreteState 类来添加行为是非常容易的。因此状态模式不仅改善了扩展应用程序行为时的灵活性而且全面提高了代码的可维护性。
状态模式的不足:
类爆炸由于每个状态都需要在 ConcreteState 的帮助下定义因此我们可能导致创建了太多功能较为单一的类。我们不妨考虑有限状态机的情况——如果有许多状态但每个状态与另一个状态没有太大不同我们仍然需要将它们写成单独的 ConcreteState 类。这既增加了代码量又使得状态机的结构更加难以审查。随着每个新行为的引入即使添加行为只是添加一个 ConcreteStateContext 类都需要进行相应的更新以处理每个行为。这使得上下文行为更容易受到每个新的行为的影响。
反模式
反模式是处理重复出现问题的某些解决方案的后果。
反模式可以分为两大类。1.软件开发反模式。2.软件架构反模式。
软件开发反模式
下面将列举软件开发中的几种反模式。
1.意大利面条式代码
以特殊的方式开发结构软件控制流会变得错综复杂。
意大利面条式代码的典型成因包括
对面向对象编程和分析的无知没有考虑产品的架构或设计快餐式思维。
当遭遇意大利面条式代码时就会面临下列问题
结构的重用性将会降到最低维护工作量过高进行修改时扩展性和灵活性会降低。
2.金锤
由于某个解决方案技术、设计或模块在多个项目中效果不错所以就把它推广到更多的地方。一把锤子搞定所有的钉子解决所有问题。
之所以出现金锤典型的原因有如下几个
来自不了解具体问题的高层架构师或技术领袖的建议虽然某解决方案在过去多次验证有效但当前项目却具有不同的背景和要求公司已经被这种技术“绑架”了因为他们已经在它上面投资了大量资金来培训员工或员工们对这种技术情有独钟因为已经用顺手了。
3.熔岩流
这个反模式与软件应用程序中的死代码或一段用不到的代码有关随着时间的流逝这段代码会一直留在软件中并固化其位置就像熔岩变成硬岩一样。
熔岩流的成因包括以下几个
在产品中有大量的试错代码由一个人单独编写的代码未经审查就在没有任何培训的情况下移交给了其他开发团队软件架构或设计的初始思想是通过代码库实现的但没有人能理解它。
熔岩流的症状如下
开发的测试工作如果完成的话具有很低的代码覆盖率代码中含有莫名奇妙的注释过时的接口或开发人员需要围绕既有代码展开工作
4.复制粘贴或剪切粘贴式编程
这是最常见的反模式之一。有些开发人员为了提高开发进度经常会原封不动地复制这些片段并用于自己的应用程序中。
导致复制粘贴或剪切粘贴式编程的原因如下
新手开发者不习惯编写代码或不知道如何开发代码快速修复bug或“急就章”式的开发代码重复无法满足跨模块标准化以及代码结构化的要求缺乏长远打算或深谋远虑。
剪切粘贴或复制粘贴式编程的后果包括
多个软件应用程序存在同种类型的问题维护成本会更高同时bug的生命周期也会变得更长较少的模块化代码库相同的代码会散落于多处继承问题。
软件架构反模式
1.重新发明轮子
重新审视相同的问题并为它重新设计解决方案并没有什么意义这基本上就是重新发明轮子。
导致重新发明轮子的原因如下
缺乏中央文档或存储库来讲解架构级问题和存放已实现的解决方案社区或公司内的技术领袖之间缺乏沟通组织中遵循的流程是从头开始构建的通常情况下这样的流程是不成熟的并且流程的实现通常是不严谨的并且很难坚持。
这种反模式的后果如下所示
解决一个标准问题的解决方案太多其中许多解决方案考虑得并不周全会耗费工程团队更多的时间和资源导致预算超标上市时间延后封闭的系统架构仅适用于一种产品的架构、重复劳动和糟糕的风险管理。
2.供应商套牢
正如这种反模式的名称所示产品公司往往依赖于供应商提供的某些技术。这些技术对于他们的系统来说如此密不可分以至于系统很难摆脱这些技术。
以下是导致供应商锁定的原因
熟悉供应商公司的权威人士以及技术采购的可能折扣基于营销和销售业务而不是技术评估选择的技术在当前项目中使用经过验证的技术验证表明使用此技术的投资回报率非常高即使它不适合当前项目的需要或要求技术人员/开发人员已经接受过相关技术的培训。
供应商锁定的后果如下所示
公司产品的发布周期和维护周期直接取决于供应商的发布时间该产品是围绕该技术而不是根据客户的要求开发的产品上市时间不可靠不能满足客户的期望。
3.委员会设计
有时根据组织中的流程一群人会坐在一起来设计特定的系统所得到的软件架构通常是复杂的或不合格的。因为这涉及太多的思维过程并且这些设计思想可能是由没有相应的技能或相应产品设计经验的技术专家所提出的。
委员会设计的原因如下
根据组织的流程产品的架构或设计是由众多的利益相关者批准的没有指定单独的联系人或负责设计的架构师由营销或技术专家确定设计优先级而不是由客户反馈来确定。
与该模式有关的症状如下所示
开发人员和架构师之间的观点冲突即使在设计完成后依旧如此过于复杂的设计很难记录规格或设计的任何改动都需要经过多次审查导致实现延迟。