行为模式-责任链模式
https://refactoringguru.cn/design-patterns/chain-of-responsibility
行为模式-责任链模式亦称: 职责链模式、命令链、CoR、Chain of Command、Chain of Responsibility
意图责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
问题假如你正在开发一个在线订购系统。 你希望对系统访问进行限制, 只允许认证用户创建订单。 此外, 拥有管理权限的用户也拥有所有订单的完全访问权限。
简单规划后, 你会意识到这些检查必须依次进行。 只要接收到包含用户凭据的请求, 应用程序就可尝试对进入系统的用户进行认证。 但如果由于用户凭据不正确而导致认证失败, 那就没有必要进行后续检查了。
在接下来的几个月里, 你实现了后续的几个检查步骤。
一位同事认为直接将原始数据传递给订购系统存在安全隐患。 因此你新增了额外的验证步骤来清理请求中的数据。
过了一段时间, 有人注意到系统无法抵御暴力密码破解方式的攻击。 ...
结构型模式-代理模式
https://refactoringguru.cn/design-patterns/proxy
结构型模式-代理模式亦称: Proxy
意图代理模式是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。
问题为什么要控制对于某个对象的访问呢? 举个例子: 有这样一个消耗大量系统资源的巨型对象, 你只是偶尔需要使用它, 并非总是需要。
你可以实现延迟初始化: 在实际有需要时再创建该对象。 对象的所有客户端都要执行延迟初始代码。 不幸的是, 这很可能会带来很多重复代码。
在理想情况下, 我们希望将代码直接放入对象的类中, 但这并非总是能实现: 比如类可能是第三方封闭库的一部分。
解决方案代理模式建议新建一个与原服务对象接口相同的代理类, 然后更新应用以将代理对象传递给所有原始对象客户端。 代理类接收到客户端请求后会创建实际的服务对象, 并将所有工作委派给它。
这有什么好处呢? 如果需要在类的主要业务逻辑前后执行一些工作, 你无需修改类就能完成这项工作。 由于代理实现的接口与原类相同, 因此你可将其 ...
结构型模式-享元模式
https://refactoringguru.cn/design-patterns/flyweight
结构型模式-享元模式亦称: 缓存、Cache、Flyweight
意图享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的内存容量中载入更多对象。
问题假如你希望在长时间工作后放松一下, 所以开发了一款简单的游戏: 玩家们在地图上移动并相互射击。 你决定实现一个真实的粒子系统, 并将其作为游戏的特色。 大量的子弹、 导弹和爆炸弹片会在整个地图上穿行, 为玩家提供紧张刺激的游戏体验。
开发完成后, 你推送提交了最新版本的程序, 并在编译游戏后将其发送给了一个朋友进行测试。 尽管该游戏在你的电脑上完美运行, 但是你的朋友却无法长时间进行游戏: 游戏总是会在他的电脑上运行几分钟后崩溃。 在研究了几个小时的调试消息记录后, 你发现导致游戏崩溃的原因是内存容量不足。 朋友的设备性能远比不上你的电脑, 因此游戏运行在他的电脑上时很快就会出现问题。
真正的问题与粒子系统有关。 每个粒子 (一颗子弹、 一枚导弹或一块弹 ...
结构型模式-外观模式
https://refactoringguru.cn/design-patterns/facade
结构型模式-外观模式亦称: 门面模式、Facade
意图外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。
问题假设你必须在代码中使用某个复杂的库或框架中的众多对象。 正常情况下, 你需要负责所有对象的初始化工作、 管理其依赖关系并按正确的顺序执行方法等。
最终, 程序中类的业务逻辑将与第三方类的实现细节紧密耦合, 使得理解和维护代码的工作很难进行。
解决方案外观类为包含许多活动部件的复杂子系统提供一个简单的接口。 与直接调用子系统相比, 外观提供的功能可能比较有限, 但它却包含了客户端真正关心的功能。
如果你的程序需要与包含几十种功能的复杂库整合, 但只需使用其中非常少的功能, 那么使用外观模式会非常方便,
例如, 上传猫咪搞笑短视频到社交媒体网站的应用可能会用到专业的视频转换库, 但它只需使用一个包含 encode(filename, format)方法 (以文件名与文件格式为参数进行编码的方法) 的类即可。 在创建这个类并将其连接到视频转换 ...
结构型模式-装饰模式
https://refactoringguru.cn/design-patterns/decorator
结构型模式-装饰模式亦称: 装饰者模式、装饰器模式、Wrapper、Decorator
意图装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
问题假设你正在开发一个提供通知功能的库, 其他程序可使用它向用户发送关于重要事件的通知。
库的最初版本基于 通知器Notifier类, 其中只有很少的几个成员变量, 一个构造函数和一个 send发送方法。 该方法可以接收来自客户端的消息参数, 并将该消息发送给一系列的邮箱, 邮箱列表则是通过构造函数传递给通知器的。 作为客户端的第三方程序仅会创建和配置通知器对象一次, 然后在有重要事件发生时对其进行调用。
此后某个时刻, 你会发现库的用户希望使用除邮件通知之外的功能。 许多用户会希望接收关于紧急事件的手机短信, 还有些用户希望在微信上接收消息, 而公司用户则希望在 QQ 上接收消息。
这有什么难的呢? 首先扩展 通知器类, 然后在新的子类中加入额外的通知方法。 现在客户端要对所需 ...
结构型模式-组合模式
https://refactoringguru.cn/design-patterns/composite
结构型模式-组合模式亦称: 对象树、Object Tree、Composite
意图组合模式是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。
问题如果应用的核心模型能用树状结构表示, 在应用中使用组合模式才有价值。
例如, 你有两类对象: 产品和 盒子 。 一个盒子中可以包含多个 产品或者几个较小的 盒子 。 这些小 盒子中同样可以包含一些 产品或更小的 盒子 , 以此类推。
假设你希望在这些类的基础上开发一个定购系统。 订单中可以包含无包装的简单产品, 也可以包含装满产品的盒子……以及其他盒子。 此时你会如何计算每张订单的总价格呢?
你可以尝试直接计算: 打开所有盒子, 找到每件产品, 然后计算总价。 这在真实世界中或许可行, 但在程序中, 你并不能简单地使用循环语句来完成该工作。 你必须事先知道所有 产品和 盒子的类别, 所有盒子的嵌套层数以及其他繁杂的细节信息。 因此, 直接计算极不方便, 甚至完全不可行。
解决方案组 ...
结构型模式-桥接模式
https://refactoringguru.cn/design-patterns/bridge
结构型模式-桥接模式亦称: Bridge
意图桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。
问题抽象? 实现? 听上去挺吓人? 让我们慢慢来, 先考虑一个简单的例子。
假如你有一个几何 形状Shape类, 从它能扩展出两个子类: 圆形Circle和 方形Square 。 你希望对这样的类层次结构进行扩展以使其包含颜色, 所以你打算创建名为 红色Red和 蓝色Blue的形状子类。 但是, 由于你已有两个子类, 所以总共需要创建四个类才能覆盖所有组合, 例如 蓝色圆形BlueCircle和 红色方形RedSquare 。
在层次结构中新增形状和颜色将导致代码复杂程度指数增长。 例如添加三角形状, 你需要新增两个子类, 也就是每种颜色一个; 此后新增一种新颜色需要新增三个子类, 即每种形状一个。 如此以往, 情况会越来越糟糕。
解决方案问题的根本原因是我们试图在两个独立的维度——形状与颜色——上扩 ...
结构型模式-适配器模式
https://refactoringguru.cn/design-patterns/adapter
结构型模式-适配器模式亦称: 封装器模式、Wrapper、Adapter
意图适配器模式是一种结构型设计模式, 它能使接口不兼容的对象能够相互合作。
问题假如你正在开发一款股票市场监测程序, 它会从不同来源下载 XML 格式的股票数据, 然后向用户呈现出美观的图表。
在开发过程中, 你决定在程序中整合一个第三方智能分析函数库。 但是遇到了一个问题, 那就是分析函数库只兼容 JSON 格式的数据。
你可以修改程序库来支持 XML。 但是, 这可能需要修改部分依赖该程序库的现有代码。 甚至还有更糟糕的情况, 你可能根本没有程序库的源代码, 从而无法对其进行修改。
解决方案你可以创建一个适配器。 这是一个特殊的对象, 能够转换对象接口, 使其能与其他对象进行交互。
适配器模式通过封装对象将复杂的转换过程隐藏于幕后。 被封装的对象甚至察觉不到适配器的存在。 例如, 你可以使用一个将所有数据转换为英制单位 (如英尺和英里) 的适配器封装运行于米和千米单位制中的对象。
适配器不仅可以转换 ...
创建型模式-单例模式
https://refactoringguru.cn/design-patterns/singleton
创建型模式-单例模式亦称: 单件模式、Singleton
意图单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
问题单例模式同时解决了两个问题, 所以违反了_单一职责原则_:
保证一个类只有一个实例。 为什么会有人想要控制一个类所拥有的实例数量? 最常见的原因是控制某些共享资源 (例如数据库或文件) 的访问权限。
它的运作方式是这样的: 如果你创建了一个对象, 同时过一会儿后你决定再创建一个新对象, 此时你会获得之前已创建的对象, 而不是一个新对象。
注意, 普通构造函数无法实现上述行为, 因为构造函数的设计决定了它必须总是返回一个新对象。
为该实例提供一个全局访问节点。 还记得你 (好吧, 其实是我自己) 用过的那些存储重要对象的全局变量吗? 它们在使用上十分方便, 但同时也非常不安全, 因为任何代码都有可能覆盖掉那些变量的内容, 从而引发程序崩溃。
和全局变量一样, 单例模式也允许在程序的任何地方访问特定对象。 但 ...
创建型模式-原型模式
https://refactoringguru.cn/design-patterns/prototype
创建型模式-原型模式亦称: 克隆、Clone、Prototype
意图原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
问题如果你有一个对象, 并希望生成与其完全相同的一个复制品, 你该如何实现呢? 首先, 你必须新建一个属于相同类的对象。 然后, 你必须遍历原始对象的所有成员变量, 并将成员变量值复制到新对象中。
不错! 但有个小问题。 并非所有对象都能通过这种方式进行复制, 因为有些对象可能拥有私有成员变量, 它们在对象本身以外是不可见的。
直接复制还有另外一个问题。 因为你必须知道对象所属的类才能创建复制品, 所以代码必须依赖该类。 即使你可以接受额外的依赖性, 那还有另外一个问题: 有时你只知道对象所实现的接口, 而不知道其所属的具体类, 比如可向方法的某个参数传入实现了某个接口的任何对象。
解决方案原型模式将克隆过程委派给被克隆的实际对象。 模式为所有支持克隆的对象声明了一个通用接口, 该接口让你能够克隆对象, 同时又无需 ...
创建型模式-生成器模式
https://refactoringguru.cn/design-patterns/builder
创建型模式-生成器模式亦称: 建造者模式、Builder
意图生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。
问题假设有这样一个复杂对象, 在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。 这些初始化代码通常深藏于一个包含众多参数且让人基本看不懂的构造函数中; 甚至还有更糟糕的情况, 那就是这些代码散落在客户端代码的多个位置。
例如, 我们来思考如何创建一个 房屋House对象。 建造一栋简单的房屋, 首先你需要建造四面墙和地板, 安装房门和一套窗户, 然后再建造一个屋顶。 但是如果你想要一栋更宽敞更明亮的房屋, 还要有院子和其他设施 (例如暖气、 排水和供电设备), 那又该怎么办呢?
最简单的方法是扩展 房屋基类, 然后创建一系列涵盖所有参数组合的子类。 但最终你将面对相当数量的子类。 任何新增的参数 (例如门廊类型) 都会让这个层次结构更加复杂。
另一种方法则无需生成子类。 你可以 ...
创建型模式-抽象工厂模式
https://refactoringguru.cn/design-patterns/abstract-factory
创建型模式-抽象工厂模式亦称: Abstract Factory
意图抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。
问题假设你正在开发一款家具商店模拟器。 你的代码中包括一些类, 用于表示:
一系列相关产品, 例如 椅子Chair 、 沙发Sofa和 咖啡桌CoffeeTable 。
系列产品的不同变体。 例如, 你可以使用 现代Modern 、 维多利亚Victorian 、 装饰风艺术ArtDeco等风格生成 椅子 、 沙发和 咖啡桌 。
你需要设法单独生成每件家具对象, 这样才能确保其风格一致。 如果顾客收到的家具风格不一样, 他们可不会开心。
此外, 你也不希望在添加新产品或新风格时修改已有代码。 家具供应商对于产品目录的更新非常频繁, 你不会想在每次更新时都去修改核心代码的。
解决方案首先, 抽象工厂模式建议为系列中的每件产品明确声明接口 (例如椅子、 沙发或咖啡桌)。 然后, 确保所有产品 ...
创建型模式-工厂方法模式
https://refactoringguru.cn/design-patterns/factory-method
创建型模式-工厂方法模式亦称:虚拟构造函数、Virtual Constructor、Factory Method
意图工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。
问题假设你正在开发一款物流管理应用。 最初版本只能处理卡车运输, 因此大部分代码都在位于名为 卡车的类中。
一段时间后, 这款应用变得极受欢迎。 你每天都能收到十几次来自海运公司的请求, 希望应用能够支持海上物流功能。
这可是个好消息。 但是代码问题该如何处理呢? 目前, 大部分代码都与 卡车类相关。 在程序中添加 轮船类需要修改全部代码。 更糟糕的是, 如果你以后需要在程序中支持另外一种运输方式, 很可能需要再次对这些代码进行大幅修改。
最后, 你将不得不编写繁复的代码, 根据不同的运输对象类, 在应用中进行不同的处理。
解决方案工厂方法模式建议使用特殊的工厂方法代替对于对象构造函数的直接调用 (即使用 new运算符)。 不用担心, 对象仍将 ...
52条SQL语句性能优化策略
52条SQL语句性能优化策略[转]
https://www.cnblogs.com/SimpleWu/p/9929043.html
1、对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引。
2、应尽量避免在where子句中对字段进行null值判断,创建表时NULL是默认值,但大多数时候应该使用NOT NULL,或者使用一个特殊的值,如0,-1作为默认值。
3、应尽量避免在where子句中使用!=或<>操作符,MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。
4、应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,可以使用UNION合并查询:select id from t where num=10 union all select id from t where num=20。
5、in和not in也要慎用,否则会导致全表扫描,对于连续的数值,能 ...
Flutter常用控件
Flutter常用控件
dart生成uml
Dart使用PlantUML生成uml
安装了flutter,并且已经将bin文件添加到环境变量中
PlantUML Web Server
开源工具,使用简单的文字描述画UML图。 (plantuml.com)
1.下载工具1git clone https://hub.fastgit.org/glesica/dcdg.dart.git
2.安装1dart pub global activate -s path .
安装到C:\Users\<name>\AppData\Local\Pub\Cache\bin
3.运行1234567#Available builders:# * plantuml - PlantUML builder that attempts to be feature-complete# * dot - Graphviz builder that only handles inheritance# * nomnoml - Nomnoml builder for embedding diagrams in web pages#dart pub g ...
发布Android版APP
发布Android版APP在典型的开发周期中,您将使用flutter run命令行或者IntelliJ中通过工具栏运行和调试按钮进行测试。默认情况下,Flutter构建应用程序的debug版本。
当您准备好为Android准备的release版时,例如要发布到应用商店,请按照此页面上的步骤操作。
检查 App Manifest查看默认应用程序清单文件(位于<app dir>/android/app/src/main/中的AndroidManifest.xml文件),并验证这些值是否正确,特别是:
application: 编辑 application 标签, 这是应用的名称。
uses-permission: 如果您的应用程序代码不需要Internet访问,请删除android.permission.INTERNET权限。标准模板包含此标记是为了启用Flutter工具和正在运行的应用程序之间的通信。
查看构建配置查看默认[Gradle 构建文件][gradlebuild]”build.gradle”,它位于<app dir>/android/app/,验证 ...
功能实现思路
功能实现思路自定义表单系统 如何设计数据库
一个表保存表单的元数据,如ID、名称、备注、添加时间、修改时间等等。每个表单一行记录。
一个表保存表单元素的元数据,如ID、所属表单的ID、名称、样式、数据类型、顺序、备注等等。每个元素一条记录。
以上是设计表单需要保存的数据,下面是填写表单要保存的数据。
一个表保存表单数据记录的元数据,包括表单记录ID,对应的表单ID,填写人ID、填写时间、填写情况(是否填写完毕)等等。
一个表保存填写填写的表单数据,包括所属的表单记录ID、对应的表单元素ID、所填写的数据。这个可以不需要单独的ID,由记录ID和元素ID组成联合主键(当然,你要用单独ID也未尝不可)。
如果要保存历史记录,还要设计单独的表来保存。
快速搭建一个TypeScript项目
快速搭建一个TypeScript项目在团队开发中为了更好的协作,我们应该在项目中制定各种规则,比如:代码风格、变量命名、文件命名、git commit 提交格式等等。 这篇文章就介绍如何搭建快速搭建一个具有自定义规则的 TypeScript 项目。
创建项目1234$ mkdir ts-project$ cd ts-project$ yarn init$ git init
创建.gitignore123456789101112131415161718192021222324252627# serverserver/.DS_Storenode_modules/dist/npm-debug.log*yarn-debug.log*yarn-error.log*test/unit/coveragetest/e2e/reportsselenium-debug.logdoc/lib/# Editor directories and files.idea.vscode*.suo*.ntvs**.njsproj*.sln# cache.sass-cache/# package-lock.jsony ...
Flutter Widget生命周期
Flutter Widget生命周期
原来我一直在错误的使用 setState()?
State的生命周期
1.Widget的生命周期(1)
initState当Widget第一次插入到Widget树时会被调用,对于每一个State对象,Flutter framework只会调用一次该回调,所以,通常在该回调中做一些一次性的操作,如状态初始化、订阅子树的事件通知等。不能在该回调中调用BuildContext.dependOnInheritedWidgetOfExactType(该方法用于在Widget树上获取离当前widget最近的一个父级InheritFromWidget,关于InheritedWidget我们将在后面章节介绍),原因是在初始化完成后,Widget树中的InheritFromWidget也可能会发生变化,所以正确的做法应该在在build()方法或didChangeDependencies()中调用它。
didChangeDependencies()当State对象的依赖发生变化时会被调用;例如:在之前build() 中包含了一个InheritedWidget,然后 ...