构造型模式

构建者模式

Builder模式好处和优点
使用Builder模式必然会导致写两遍相关属性的代码和SETTER方法,看起来有点吃力不讨好。然而需要看到的是,客户端代码的可用性和可读性得到了大大提高。与此同时,构造函数的参数数量明显减少调用起来非常直观。
Builder方法另外一个优势在于,单个builder构建多个对象时Builder参数可在创建期间进行调整,还可以根据对象不同而进行改变。这就像我越来越推崇的以“不变”应“万变”。Builder模式特别适合那些属性个数很多的类,我认为没有必要给那些本不需要设置值传递参数(设置null)。
Builder模式在提高代码可读性的同时,使用IDE提供的代码补全功能也更加容易。Builder模式在与构造函数一起使用带来的更大优势在Josh Bloch的Effective Java第二版第2条中有详细阐述。

Builder模式的代价和缺点
使用Builder模式是肯定会增加代码量的。此外,尽管客户端的代码可读性明显改善,但随之而来的客户端代码变得更加冗长。我还是坚持这一观点:相比较参数数量的增加,相同类型的参数混在一起,可选参数的增加而言,改善代码可读性更有价值。
Builder会增加个类代码,这也意味着开发者在给类增加属性时有时会忘记给该属性添加支持的builder。为了克服这个问题,通常我会将builder嵌套到类中,这样可以很容易地发现哪个相关的builder需要更新。尽管忘记的风险依旧存在,但是这风险就像忘记给类的新属性增加 toString()、 equals(Object)、 hashCode()或其他类基于是所有属性的方法一样。
在我的Builder实现中,我会用Builder的构造函数而不是set方法传递客户需要的属性。这样做的好处在于,对象总是能被一次完整的实例化,而不是靠开发人员调用时用set方法补充额外的属性完成实例化。这也体现了不可变性带来的好处。然而,相应地也会造成自己设定的属性方法可读性降低。

总结
构建对象时,如果碰到类有很多参数——其中很多参数类型相同而且很多参数可以为空时,我更喜欢Builder模式来完成。当参数数量不多、类型不同而且都是必须出现时,通过增加代码实现Builder往往无法体现它的优势。在这种情况下,理想的方法是调用传统的构造函数。再者,如果不需要保持不变,那么就使用无参构造函数调用相应的set方法吧。

个人理解:构建着模式,通过重写了各个set方法使得设置值看起来更加清晰。如果设置的参数不多建议使用,过多则不建议显得太长,反而不易阅读。

参考文章http://www.importnew.com/6605.html

简单工厂
简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。
不修改代码的话,是无法扩展的

个人理解:所谓简单工厂即使用一个额外的类,并在该类中创建一个根据不同入参返回不同(实现了同一接口的)对象的方法。而该额外的类就是工厂类。
好处:使用者获取不用考虑选择哪个创建方法来创建对象,根据传参自然就可以获得。
坏处:无法扩展(没有遵守开放—封闭原则),要是新增加一个实现了同一接口的不同类就必须修改额外类中的方法(增加else if )。

这里写图片描述

工厂方法
工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。
在同一等级结构中,支持增加任意产品。

个人理解:不存在一个额外的类来获取实际所需的类(存在多个),而是通过每个实际所需的类都有一个对应的额外类,这些额外类(具体工厂)实现了同一个接口(抽象工厂)。每次新增加实际类就要增加一个实现了公共接口的额外类。
好处:只要创建符合规范的具体工厂并实现抽象工厂接口,就能使用。不用修改原有代码(遵守开放—封闭原则)
坏处:使用者要自行判断new 的类。每增加一产品就要增加一个产品工厂的类,增加了额外的开发量。
这里写图片描述

抽象工厂
抽象工厂是应对产品族概念的。比如说,每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法。
应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品

个人理解:工厂方法创建的是一个一维层度上的。假如实际所需的类(比如奔驰,大众)又分成多个种类(轿车,货车,客车),那么通过工厂方法创建了实际所需类(产品族),再通过简单工厂创建第二层分类(产品类)就是一种抽象工程

区别
简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

这里写图片描述

参考文章
http://blog.csdn.net/lingfengtengfei/article/details/12374469
http://blog.csdn.net/superbeck/article/details/4446177
https://www.cnblogs.com/zhangchenliang/p/3700820.html

定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
这里写图片描述

原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:
实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。
原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式。在实际应用中,原型模式很少单独出现。经常与其他模式混用,他的原型类Prototype也常用抽象类来替代。

原型模式的优点及适用场景
使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
原型模式的注意事项
使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。

个人理解:原型模式较为简单,即为原对象的拷贝 对象越复杂使用clone越快,否则则是new方法快
参考文章
http://blog.csdn.net/zhengzhb/article/details/7393528

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态
这里写图片描述

备忘录模式的结构
发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。
备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
管理角色:对备忘录进行管理,保存和提供备忘录。

备忘录模式的优缺点和适用场景
备忘录模式的优点有:
当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原。
备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理。
备忘录模式的缺点:
在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。
如果有需要提供回滚操作的需求,使用备忘录模式非常适合,比如jdbc的事务操作,文本编辑器的Ctrl+Z恢复等。

参考文章
https://www.cnblogs.com/java-my-life/archive/2012/06/06/2534942.html
https://www.cnblogs.com/java-my-life/archive/2012/06/06/2534942.html
http://blog.csdn.net/zhengzhb/article/details/7697549

发布了21 篇原创文章 · 获赞 6 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/soulonlyhlh/article/details/78634320