
设计模式
文章平均质量分 80
设计模式学习博客
GreyZeng
程序员,架构师,项目经理
展开
-
设计模式学习(二十四):Spring 中使用到的设计模式
TransactionAwareCacheDecorator 实现 Cache 接口,并且将所有的操作都委托给 targetCache 来实现,对其中的写操作添加了事务功能。BeanFactory 类和 ApplicationContext 相关类( AbstractApplicationContext、ClassPathXmlApplicationContext、FileSystemXmlApplicationContext等)定义一个实现了 ApplicationListener 的监听器;原创 2022-11-12 19:31:50 · 697 阅读 · 0 评论 -
设计模式学习(二十三):中介模式
举个简单的例子,如果一个聊天室里面的用户1和用户2要聊天,聊天室就相当于中介的地位,用户1和用户2只管调用发消息方法,聊天室即可把消息给对方。以上代码表示,聊天室将 user 说的 content 展示出来。User 中的 sendMessage 方法。上述示例的 UML 图如下。原创 2022-11-12 19:07:54 · 397 阅读 · 0 评论 -
设计模式学习(二十二):解释器模式
实际上,我们可以把自定义的告警规则,看作一种特殊“语言”的语法规则。我们实现一个解释器,能够根据规则,针对用户输入的数据,判断是否触发告警。一般来讲,监控系统支持开发者自定义告警规则,比如我们可以用下面这样一个表达式,来表示一个告警规则,它表达的意思是:每分钟 API 总出错数超过 100 或者每分钟 API 总调用数超过 10000 就触发告警。除此之外,用户可以自定义要监控的 key,比如前面的 api_error_per_minute、api_count_per_minute。这五个运算符,其中,原创 2022-11-12 17:45:33 · 411 阅读 · 0 评论 -
设计模式学习(二十一):命令模式
CopyCommand 实现这个接口,并实现。这两个方法,其他的命令也可以类似的实现出来。结合责任链模式实现多次 undo;结合备忘录模式实现事务回滚;上述示例的 UML 图如下。结合组合模式实现宏命令;原创 2022-11-12 17:15:38 · 351 阅读 · 0 评论 -
设计模式学习(二十):备忘录模式
注:其中的 Person 类需要实现序列化接口(即:实现 Serializable 接口)Windows 操作系统里的撤销操作( ctr + z );通过序列化的方式将数据存盘,然后从盘中提取并反序列化数据。用于记录对象的某个瞬间,类似快照的功能,上述示例的 UML 图如下。游戏中的「后悔药」;原创 2022-11-12 16:46:31 · 701 阅读 · 0 评论 -
设计模式学习(十九):访问者模式
假设我们需要构造一台电脑,有主板( Board ),CPU ,内存( Memory ),但是针对企业用户和个人用户,电脑组件的价格是不一样的,我们需要根据不同客户获取一台电脑的总价格。每个具体类型的访问者实现这个接口,然后定义其不同的价格策略,以公司访问者为例( CorpVisitor )做编译器的时候,需要生成 AST ,进行类型检查 根据抽象语法树,生成中间代码;Java SE 中的 FileVisitor 使用了访问者模式,使用示例。可以看到,不同的访问者,对于电脑的价格是不一样的。原创 2022-11-12 16:03:55 · 436 阅读 · 1 评论 -
设计模式学习(十八):迭代器模式
里面包括了一个 iterator 方法,所以每个实现这个容器接口的具体容器类型,都必须自定义 iterator 方法, 然后定义一个 Iterator 接口 Iterator_, 具体容器中可以增加一个内部类来专门实现这个接口,我们可以在容器中,为每个元素保存两个时间戳,一个是添加时间戳 addTimestamp,一个是删除时间戳 delTimestamp。同时,每个迭代器也保存一个迭代器创建时间戳 snapshotTimestamp,也就是迭代器对应的快照的创建时间戳。的元素,才是属于这个迭代器的快照。原创 2022-11-12 15:21:52 · 250 阅读 · 0 评论 -
设计模式学习(十七):状态模式
Person 有 Cry , Smile , Say 三种行为,但是在不同状态( SadState , HappyState )下,这三种行为不一样,Person 就可以根据不同的状态来执行 cry ,say ,smile 的行为了。对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。上述示例的 UML 图如下。Happy 状态下同理。原创 2022-11-12 15:01:34 · 209 阅读 · 0 评论 -
设计模式学习(十六):责任链模式
不过,更为优雅的一种方式是设计一个 FilterChain ,把所有的 Filter 都加入到这个 FilterChain 里面,对于 Msg 直接去调用 FilterChain 的过滤方法即可把 FilterChain 中的所有 Filter 都执行,而且还可以很灵活指定 Filter 顺序。我们有多个过滤规则,比如第一个规则是:过滤 scripts 这个关键字(实际的规则可能很复杂,目前只是举这个简单例子来说明情况)然后,可以抽象一个 Filter 接口,各种过滤规则无非就是实现这个接口即可。原创 2022-11-12 14:37:28 · 218 阅读 · 0 评论 -
设计模式学习(十五):策略模式
进一步抽象,如果我想让 Sorter 这个工具类不仅可以对猫进行各种策略的排序(基于比较的排序算法),还可以对狗进行各种策略的排序(基于比较排序算法),可以将 Sorter 定义成泛型。我们可以把体重从小到大这个看成是一个策略,后续可能衍生其他的策略,比如: 按身高从高到低,体重从小到大,体重一样的身高从高到低……假设我们有一个猫类,这个类里面有体重和身高这两个属性,给你一个猫的集合,然后需要你按猫的体重从小到大排序。调用的时候, 泛型版本的 Sorter 可以对猫和狗都进行基于特定排序策略的排序。原创 2022-11-12 12:58:18 · 159 阅读 · 0 评论 -
设计模式学习(十四):模板方法
MyBatis 中的 BaseExecutor 定义了模板方法,子类 ReuseExecutor 、SimpleExecutor 、BatchExecutor 和 ClosedExecutor 实现了对应的模板方法。假设我们要设计一系列的测试用例,然后运行这些测试用例的的测试方法,可以抽象出一个 TestCase 的模板方法,代码如下。Java SE 中的 AbstractList 类定义了一些模板方法,ArrayList 作为子类实现了对应的模板方法。主方法在调用的时候,直接调用其。原创 2022-11-12 06:53:08 · 710 阅读 · 0 评论 -
设计模式学习(十三):观察者模式
由上可知,Button 中持有了一个列表,这个列表里面装的就是所有事件的列表,我们可以把事件绑定到这个按钮的事件列表中,这样就可以实现按钮执行 press 操作的时候,把对应的事件触发执行了。界面上的按钮上一般都可以绑定事件,当我们按下按钮的时候,可以触发这些事件的执行,这里就可以用观察者模式来做, 我们先定义按钮这个对象。在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。的时候,对应的 listener1 和 listener2 就可以执行了。原创 2022-11-11 21:32:10 · 563 阅读 · 0 评论 -
设计模式学习(十二):享元模式
我们知道,只有使用过被丢弃的对象才是垃圾回收的目标,所以,我们需要想办法在处理大量请求的同时,尽量少的产生这种一次性对象。最有效的方法就是,优化你的代码中处理请求的业务逻辑,尽量少的创建一次性对象,特别是占用内存较大的对象。不过,跟IntegerCache 不同的是,它并非事先创建好需要共享的对象,而是在程序的运行期间,根据需要来创建和缓存字符串常量。当我们使用自动装箱或者。在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。原创 2022-11-11 15:33:16 · 267 阅读 · 0 评论 -
设计模式学习(十一):组合模式
MyBatis解析各种 Mapping 文件中的 SQL 语句时,设计了一个非常关键的类叫作 SqlNode,XML 中的每一个 Node 都会被解析为一个 SqlNode 对象,最后把所有 SqlNode 都拼装到一起,就成为一条完整的 SQL 语句。其中, BranchNode 为分支节点, LeafNode 是叶子节点 达到的效果就是打印如下的形式。组合模式中,最常用的一个用法就是目录层级的遍历,话不多说,直接上代码,主方法中。原创 2022-11-11 09:15:09 · 341 阅读 · 0 评论 -
设计模式学习(十):门面模式
它是 Linux 操作系统暴露给开发者的一组“特殊”的编程接口,它封装了底层更基础的 Linux 内核调用。再比如, Linux 的 Shell 命令,实际上也可以看作一种门面模式的应用。它继续封装系统调用,提供更加友好、简单的命令,让我们可以直接通过执行命令来跟操作系统交互。如果每次我们制造一个房子都要分别调用这三个方法,就会比较麻烦一些,我们可以设置一个门面,这个门面封装了这三个步骤,后续建造房子,只需要调用这个门面即可。门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用。原创 2022-11-11 03:11:35 · 476 阅读 · 0 评论 -
设计模式学习(九):装饰器模式
然后我们定义 Sharp 的装饰类 SharpDecorator ,这个类是所有装饰器类的抽象类,后续的装饰器只需要实现这个抽象类就可以对 Sharp 进行各种装饰了,顾名思义,就是对某个方法或者对象进行装饰,举个简单的例子,有个圆形类 Circle,我需要把这个圆形的涂上红色,其实就是新增一个装饰器来装饰这个圆形类。如果要让装饰器通用一些,可以处理圆形类对应的抽象类 Sharp ,那么对于任意 Sharp 的子类,都可以用红色装饰器来涂红色。装饰器模式中,装饰器类附加的是跟原始类相关的增强功能。原创 2022-11-10 20:06:55 · 364 阅读 · 0 评论 -
设计模式学习(八):桥接模式
如上代码,礼物 Flower 被包装成了一个 WarmGift 送给 MM ,WarmGift 和 WildGift 都是 Gift 的一种抽象,Flower 和 Book 都算 Gift 的一种具体实现,)注册到 DriverManager 之后,后续所有对 JDBC 接口的调用,都会委派到对具体的 Driver 实现类来执行。桥接模式是一种结构型模式。使用桥接模式,可以将抽象和具体的发展单独分支(即:抽象中持有一个具体的引用)是一个类与另一个类的组合,那么桥接模式是一组类和另外一组类的组合。原创 2022-11-10 13:00:23 · 493 阅读 · 0 评论 -
设计模式学习(七):适配器模式
这个适配器就是根据不同类型来构造不同的播放器的,然后定义一个 ExtendMediaPlayer ,这个 ExtendMediaPlayer 应该要拥有 PlayerAdapter 的能力,所以在 ExtendMediaPlayer 中组合了 PlayAdapter ,代码如下。新版本的 JDK 用 Iterator 类替代 Enumeration 类来遍历容器,但是为了适配旧 API,采用了适配器模式,适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口。原创 2022-11-09 09:30:48 · 228 阅读 · 0 评论 -
设计模式学习(六):代理模式
在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志、缓存等,我们将这些附加功能与业务功能解耦,放到代理类中统一处理。举个例子,假设需要在某个类的某段代码的前后加上日志记录,就可以通过静态代理的方式实现,代码如下。还是以上例说明,如果需要通过 JDK 自带的方式来完成上述功能,可以这样来做。无论是 JDK 自带动态代理还是 Cglib 实现动态代理,底层都是基于。JDK 自带的方式实现动态代理需要被代理对象实现一个接口,方法的前后都加上日志记录,我们可以设置一个代理类。原创 2022-11-08 20:17:48 · 404 阅读 · 0 评论 -
设计模式学习(五):原型模式
但是,如果对象中的数据需要经过复杂的计算才能得到(比如排序、计算哈希值),或者需要从 RPC 、网络、数据库、文件系统等非常慢速的 I/O 中读取,每次读取一次的代价都很高,在这种情况下,我们就可以利用原型模式,从其他已有对象中直接拷贝得到,而不用每次在创建新对象的时候,都重复执行这些耗时的操作。如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段的值都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。原创 2022-11-08 14:27:29 · 262 阅读 · 0 评论 -
设计模式学习(四):建造者模式
中还有一个例子, 假设我们抽象出一个披萨类,各种各样的披萨均可以继承披萨这个抽象类来实现自己的具体类型的披萨。我们在对一个实体类进行属性的 get 或 set 的时候,可以通过封装一些常用的构造方法来简化实体类的构造。抽象类有抽象的 Builder ,具体类有具体的 Builder。其中的 Builder 方法是抽象的,所以子类需要实现具体的 Builder 策略,实际应用有非常多,很多组件都提供这样的构造方式,比如。另一种披萨的具体实现 Calzone。一种披萨的具体实现 NyPizza。原创 2022-11-08 07:43:51 · 212 阅读 · 0 评论 -
设计模式学习(三):工厂模式
对于现代工厂还是古代工厂,只需要继承 AbstractFactory 这个抽象类,实现 createTransportation 方法即可,以现代工厂为例。举例,现在需要通过工厂来制造交通工具,如果是现代的工厂,制造的就是汽车,如果是古代的工厂,制造的就是马车, 我们可以先把工厂抽象出来,工厂方法中,我们可以定义对应产品的对应工厂,以上面这个鼠标的例子为例,我们可以增加工厂的接口。工厂模式是创建型模式,工厂模式分为:简单工厂,工厂方法和抽象工厂三种类型。工厂方法的优点是符合开闭原则,但是缺点也很明显,原创 2022-11-07 22:36:18 · 360 阅读 · 0 评论 -
设计模式学习(二):单例模式
不过,如果初始化耗时长,那最好不要等到真正要用它的时候,才去执行这个耗时长的初始化过程,这会影响到系统的性能,我们可以将耗时的初始化操作,提前到程序启动的时候完成,这样就能避免在程序运行的时候,再去初始化导致的性能问题。进程在使用这个单例对象的时候,需要先从外部共享存储区中将它读取到内存,并反序列化成对象,然后再使用,使用完成之后还需要再存储回外部共享存储区。表示全局唯一类,比如配置信息类,在系统中,只有一个配置文件,当配置文件加载到内存中,以对象形式存在,也理所应当只有一份;原创 2022-11-07 16:25:55 · 271 阅读 · 0 评论 -
设计模式学习(一):设计原则
原因就是类 B 在给方法起名时无意中重写了父类的方法,造成所有运行相减功能的代码全部调用了类 B 重写后的方法,造成原本运行正常的功能出现了错误。在实际编程中,我们常常会通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的几率非常大。方法,每次增加一种 Shape 类型,只需要新增一个类,并实现 Shape 接口即可,这样就实现了对扩展开放,而且也不需要修改 GraphicEditor 中的。原创 2021-11-05 13:33:01 · 304 阅读 · 0 评论