设计模式
rosepicker
这个作者很懒,什么都没留下…
展开
-
关于设计模式学习的浅见
设计模式可以说是前人在实践中的心血结晶,它并不是一门知识,而是强操作性的技能。所在在学习时,应该在实践中不断运用并进行强化。学习任何东西,最主要的是掌握其思想,深刻理解,然后在探究其如何去实现该核心思想。编程就像艺术和摄影一样,需要不间断地实践来磨练基本功,需要进一步就必须深刻掌握并运用其内在的核心思想,从而才能真正达到运用自如。对于设计模式的学习应该包含以下几点:1.原创 2017-02-09 14:19:30 · 180 阅读 · 0 评论 -
事件队列
事件队列解耦发出消息或事件的时间和处理它的时间。在队列中按先入先出的顺序存储一系列通知或请求,发送通知时,将请求放入队列并返回,处理请求的系统之后稍晚从队列中获取请求并处理,解耦发送者和接收者。如果你只是想解耦接收者和发送者,可以使用观察者模式和命令模式,但解耦某些需要及时处理的东西时需要使用队列。队列将控制权从发送者那里拿走,接收者可以延迟处理,合并或忽视请求,当发送者需要回复时,队原创 2017-04-19 13:49:44 · 823 阅读 · 0 评论 -
组件模式
当代码耦合时,将不同系统捆绑成一个代码球,此时就可以使用该模式从而允许单一的实体跨越多个领域而不会导致这些领域彼此耦合,为了保持领域之间相互分离,将每部分代码放入各自的组件类中。使用场景:1.有一个涉及了多个领域的类,而你想要保持这些领域互相隔离2.一个类正在变大而且越来越难以使用3.想要能定义一系列分享不同能力的类,但是使用继承无法让你精确选取要重用的部分使用原创 2017-04-19 10:51:37 · 844 阅读 · 0 评论 -
子类沙盒
子类沙盒的目的:使用一个基类提供的操作集合进而在子类中定义行为。一个基类定义了一个抽象的沙盒方法和一些提供的操作。通过设置他们为保护状态来保证它们仅供子类使用,每个继承的沙盒子类针对父类提供的操作来实现沙盒函数。将所有的耦合都聚集到基类,子类就明显地与其他类更加独立。当你发现基类有大量子类的时候,这意味着数据驱动的方法可能更适合。找到一种定义数据的行为的方法,而不是用大量的代码来定义。原创 2017-04-18 16:00:38 · 312 阅读 · 0 评论 -
对象池
放弃单独地分配和释放对象,从固定的池子中重用对象,以提高性能和内存使用率。在条件比较严苛的环境下,碎片意味这在堆中的空余控件被打碎成了许多小的内存碎片,而不是大的连续内存块,这是致命的。一个简单的方案是在开始时取一大块内存,然后结束时在释放它,但这对游戏运行时创建和销毁事物的系统是痛苦的。定义一个池对象,其初始化时创建一组可重用对象(通常使用一次连续的分配),其中每个可重用对象都支持查原创 2017-03-16 16:15:04 · 233 阅读 · 0 评论 -
数据局部性
现代CPU有缓存来加速内存读取,它可以更快的读取最近访问过的内存的眦邻内存,通过合理组织数据,提高内存局部性,保证数据以处理顺序排列在连续内存上,充分使用CPU缓存来加速内存读取。数据局部性的第一准则是在遇到性能问题时使用,优化会使使代码更加复杂,更加缺乏灵活性。使用本模式时要确认你的性能问题确实是由缓存不命中引发的,通过工具来找到糟糕的缓存使用。现代软件通过抽象来解耦代码块,抽象几乎原创 2017-03-16 14:02:48 · 1234 阅读 · 0 评论 -
状态模式
状态模式中的行为由状态来决定,其把对象的行为包装在不同的状态对象里。当一个对象的内在状态改变的时候,其行为也随之改变,这个对象看起来好像是改变了其类。使用场景:一个对象的行为取决于它的状态,运行时根据状态来改变它的行为;代码中包含大量与对象状态有关的条件语句通用UML:优点:将所有与一个特定的状态相关的行为都放入一个状态对象,提供更好的方法来组织与特定状原创 2017-03-15 11:37:55 · 128 阅读 · 0 评论 -
单例模式
单例模式是应用最广的模式之一。在应用中,对于很耗资源的对象,比如线程池,缓存系统等,没有理由让它构造多个实例,只需要拥有一个全局对象。单例模式保证只有一个实例存在。确保某个类只有一个对象的场景,避免产生多个对象消耗过多资源或一个对象需要消耗的资源过多,比如访问IO和数据库等资源单例模式UML图:单例模式的实现方法有多种,其中有些存在同步或者效率问题,推荐原创 2017-03-13 15:46:42 · 199 阅读 · 0 评论 -
原型模式
原型模型多用于创建复杂的或者构造耗时的实例,这种情况复制一个已经存在的实例可使程序运行更高效。通过复制构造实例不一定使用场景:类初始化需要消化非常多的资源,通过原型拷贝避免这些消耗;通过new产生一个对象需要非常繁琐的数据准备或访问权限;一个对象需要提供给其他对象访问,而各个调用者可能都需要修改其值,原型模式提供保护性拷贝通用UML:通过clon原创 2017-03-14 16:53:26 · 177 阅读 · 0 评论 -
观察者模式
观察者模式的重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小,甚至毫无依赖。UI系统需要一套机制来使UI层和具体的业务逻辑解耦,观察者模式这个时候就可以派上用场。观察者模式就是一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。使用场景:关联行为场景,关联行为是可拆分的,而不是组合关系;事件多级触发场景;跨系统的消息交换场景,如消原创 2017-03-14 15:06:48 · 311 阅读 · 0 评论 -
命令模式
命令模式就是将一系列的方法调用封装,用户只需调用一个方法执行,那么所有这些被封装的方法就会被挨个执行调用,从而进行解耦,从而更具灵活性。将请求封装成对象,用户使用不同的请求把客户端参数化,对请求排队或记录请求日志,以及支持可撤销的操作。需要抽象出待执行的动作,然后以参数的形式提供出来。需要支持取消操作。需要支持事务操作。支持修改日志功能,当系统崩溃时,这些修改可以重做。命令原创 2017-03-14 14:12:57 · 221 阅读 · 0 评论 -
双缓冲模式
定义缓冲类封装缓冲:一段可改变的状态。缓冲被增量的修改,外部代码将修改视为单一的原子操作。类保存下一个缓冲和当前缓冲。从当前缓冲区读取数据,将数据写入下一个缓冲区,当改变完成后,将当前缓冲区和下一个缓冲区交换。使用场景:1.需要维护一些增量修改的状态2.修改到一半时,状态可能会被外部请求3.防止请求状态的外部代码知道内部的工作方式4.想要读取状态,而且不想等着修改完成原创 2017-03-20 10:47:25 · 541 阅读 · 0 评论 -
脏标识模式
将工作延期至需要其结果时才去执行,避免不必要的工作。游戏中进行位置变化时,递归调用其所有子对象。调用父节点相关的变换对对象的自身变换进行变化,计算对象的世界变换。如果在游戏中每一帧都进行计算的话,其中有些部分的位置是没有变换的,所有只需计算那些位置发生变换的对象。如果每次变换都立即更新世界变换,那么浪费CPU进行无效的运算。解耦自身变换和世界变换,在一次批处原创 2017-03-20 09:53:04 · 1329 阅读 · 0 评论 -
设计模式的六大原则
当编写代码量比较大的项目时,并且随着需求的变更,总是会发现代码会变得越来越不可维护,越来越像坨shit。其实这是一个普遍的问题的,前人们在多年的工程实践中总结出了一系列应对方法,而这些方法就是设计模式。设计模式的六大原则:1.单一职能原则:每一个类最好具备单一职能,而不是一个类行使多个职能,这样会很臃肿而且系统划分不够清晰2.开闭原则:对扩展开放,对修改关闭。现实当中很难完全做原创 2017-02-27 15:16:29 · 185 阅读 · 0 评论 -
代理模式
有时候可能无法或不想直接访问直接访问这个对象,或者访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端额透明性,委托对象和代理需要实现相同接口,代理模式用来控制对其代理对象的访问。代理模式的UML图:通过类图其实很好理解,Client通过ProxySubject来来访问RealSubject。代理模式分为动态代理和静态代理。静态代理就是代码运行前代理类的cl原创 2017-02-28 11:31:12 · 196 阅读 · 0 评论 -
装饰者模式
当需要采用透明的方式来动态扩展对象的功能时,又不想使用继承关系,那么装饰者模式就是替代方案。装饰者模式的应用场景:需要透明且动态地扩展类的功能时装饰者模式UML如下:装饰者模式是继承关系的替代方案,对所装饰的对象增强功能。装饰者模式其实在生活中无处不在,比如人穿衣服,再如电脑主板,通过不断在其上添加cpu,显卡,内存条等来增加功能。原创 2017-02-28 10:11:55 · 148 阅读 · 0 评论 -
策略模式
在项目中,我们经常会遇见一个功能需要采用多种算法或策略的情况,此时,我们写一个类来实现多种算法或策略以及在一个方法中通过if/else语句来实现多种算法或策略,这些方法称为硬编码(实际上我就这么干过 - -)。这样做违反了单一职能原则和开闭原则,会导致之后的代码很难维护。策略模式的应用场景:1.针对同一类型的问题的多种处理方式,仅仅是具体行为有差别2.需要安全的封装多种同一类型原创 2017-02-28 09:01:49 · 205 阅读 · 0 评论 -
服务定位器
服务定位器提供服务的全局接入点,避免使用者和实现服务的具体类耦合,解耦需要服务的代码和服务由谁提供以及服务在哪里。服务类定义了一堆操作的抽象接口,具体的服务提供者实现这个接口,分离的服务定位器提供了通过查询获取服务的方法,同时隐藏了服务提供者的具体细节和定位它的过程。使用服务定位器的核心难点就是它将依赖-在两块代码之间的一点耦合-推迟到运行时再连接,这具有更大的灵活度,但是代价是更难在原创 2017-04-19 15:07:40 · 312 阅读 · 0 评论