主要介绍编写不变类的主意事项:
归纳一下设计不变类的 5 条规则:
1. 不提供任何修改对象的方法。
2. 保证没有任何一个方法会被覆盖。
3. 所有的域都是 final 的。
4. 所有的域都是 private 的。
5. 如果不变类内部包括可变的子对象,保证它绝对不会被其他代码获取引用。
实例:
/**
* @author Peter Wei
*
*/
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 弱不变模式
*
* @author Peter Wei
*
*/
public class WeakImmutable {
// 属性私有,满足条件2
private int state;
// 属性私有,满足条件2
private User user;
private Integer age;
public WeakImmutable(int state, User user, Integer age) {
this.state = state;
this.user = user;
this.age = age;
}
public int getState() {
return this.state;
}
public User getUser() {
return this.user;
}
public Integer getAge() {
return this.age;
}
public void setState() {
// 对象没有任何方法修改对象的状态,满足条件1
// do nothing.
}
public static void main(String[] args) {
int state = 0;
User u = new User();
Integer age = 100;
u.setName("yes");
WeakImmutable weak = new WeakImmutable(state, u, age);
System.out.println("原始值:" + weak.getState() + ","
+ weak.getUser().getName() + "," + weak.getAge());
// 修改引用后
state = 5;
// User由于是可变对象引用,所以有影响
u.setName("no");
age = 200;
System.out.println("修改引用后:" + weak.getState() + ","
+ weak.getUser().getName() + "," + weak.getAge());
}
}结果:可以看到user的名字会改变。
原始值:0,yes,100
修改引用后:0,no,100
我们再引伸一个不可变类的例子:
在时间截止时,我们需要一一检查队列成员是不是vip,如果是可以去USA.假设是多线程环境,并且users数组是多线程共享,那么另外的线程通过users去修改users[n],这时就会把users[n]绕过时间检查而去USA.
- /**
- * 不变模式之clone
- *
- * @author Peter Wei
- *
- */
- publicclass WeakImmutableClone {
- publicstaticvoid main(String[] args) {
- User[] users = new User[3];
- users[0] = new User();
- users[0].setName("peterwei");
- users[1] = new User();
- users[1].setName("Tomssssss");
- users[2] = new User();
- users[2].setName("peterwei88");
- time4Check();
- /*
- * 时间到,我们需要一一检查队列成员是不是vip,如果是可以去USA.假设是多线程环境,并且users数组是多线程共享,
- * 那么另外的线程通过users去修改users[n],这时就会把users[n]绕过时间检查而去USA.
- */
- goUSA(users);
- }
- publicstaticvoid goUSA(User[] users) {
- // User[] tmp = new User[users.length];
- // System.arraycopy(users, 0, tmp, 0, users.length);
- for (User u : users) {
- if (checkVip(u)) {
- System.out.println("You can go!");
- } else {
- System.out.println("go away!");
- }
- }
- }
- publicstaticboolean checkVip(User user) {
- if (user.getName().startsWith("peterwei")) {
- returntrue;
- }
- returnfalse;
- }
- publicstaticvoid time4Check() {
- // 假设时间期限到,要检查上万人以上的队列。
- }
- }
/** * 不变模式之clone * * @author Peter Wei * */ public class WeakImmutableClone { public static void main(String[] args) { User[] users = new User[3]; users[0] = new User(); users[0].setName("peterwei"); users[1] = new User(); users[1].setName("Tomssssss"); users[2] = new User(); users[2].setName("peterwei88"); time4Check(); /* * 时间到,我们需要一一检查队列成员是不是vip,如果是可以去USA.假设是多线程环境,并且users数组是多线程共享, * 那么另外的线程通过users去修改users[n],这时就会把users[n]绕过时间检查而去USA. */ goUSA(users); } public static void goUSA(User[] users) { // User[] tmp = new User[users.length]; // System.arraycopy(users, 0, tmp, 0, users.length); for (User u : users) { if (checkVip(u)) { System.out.println("You can go!"); } else { System.out.println("go away!"); } } } public static boolean checkVip(User user) { if (user.getName().startsWith("peterwei")) { return true; } return false; } public static void time4Check() { // 假设时间期限到,要检查上万人以上的队列。 } }
解决方法:
在事务处理及数据大批量入库的多线程环境中,应该也会有类似的问题。所以对于这样的传入参数及上例中的不变对象引用可变对象,我们可以将其在相关构造函数及方法中复制为本地变量(数组),及使用它的深度clone,阻止相关数据与外部线程的联系。
- publicstaticvoid goUSA(User[] users) {
- User[] tmp = new User[users.length];
- System.arraycopy(users, 0, tmp, 0, users.length);
- for (User u : tmp) {
- if (checkVip(u)) {
- System.out.println("You can go!");
- } else {
- System.out.println("go away!");
- }
- }
- }
public static void goUSA(User[] users) { User[] tmp = new User[users.length]; System.arraycopy(users, 0, tmp, 0, users.length); for (User u : tmp) { if (checkVip(u)) { System.out.println("You can go!"); } else { System.out.println("go away!"); } } }
强不变模式:
一个类的实例的状态不会改变,同时它的子类的实例也具有不可变化的状态。这样的类符合强不变模式。要实现强不变模式,一个类必须首先满足弱不变模式所要求的所有条件,并且还要满足下面条件之一:
第一,所考虑的类所有的方法都应当是final,这样这个类的子类不能够置换掉此类的方法。
第二,这个类本身就是final的,那么这个类就不可能会有子类,从而也就不可能有被子类修改的问题。
不变模式在Java中的应用
如String类
- String a = "123" ;
- String a1 = "123" ;
- String a2 = "123" ;
- String a3 = "1234" ;
String a = "123" ; String a1 = "123" ; String a2 = "123" ; String a3 = "1234" ;
java虚拟机只会创建一个字符串实例,a,a1,a2对象共享一个值。遇到不同的字符串,java虚拟机会再创建一个String对象,如a3。如果程序所处理的字串有频繁的内容变化,就不宜使用String类型,而应当使用StringBuffer类型,如果需要对字串做大量的循环查询,也不宜使用String类型,应当考虑使用byte或char数组.
相关推荐
本书浅显易懂的介绍了JAVA线程相关的设计模式,通过程序范例和UML图示来一一解说,书中代码的重要部分加了标注以使读者更加容易理解,再加上图文并茂,对于初学者还是程序设计高手来说,这都是一本学习和认识JAVA...
com.javapatterns.immutable 不变模式 com.javapatterns.interfaces Java接口 com.javapatterns.interpreter 解释器模式 com.javapatterns.isp 接口隔离原则 com.javapatterns.iterator 迭代子模式 ...
简单介绍Immutable.js的一个ppt,主要用于技术分享,内容为imuutabe常用的数据类型和常用的基础api,还有immutable的原理、优缺点的分析。
工厂模式Factory 原始...不变Immutable 策略Strategy 模版Template 观察者Observer 命令Command 备忘录Memento 状态State 访问者Visitor 解释器Interpreter 调停者Mediator Iterator 责任链Chain of Responsibility
前端开源库-immutable-core不变的核心,不变的模块化框架
1.Overview of Docker the company and growth 2.Overview of Docker the latest stuff (DCUS announcements) & CaaS;...4.Docker and Immutable infrastructure/Microservices working together.
目录: 漫谈UML Introduction 1 Java语言的线程 Introduction 2 多线程...总结 多线程程序设计的模式语言 附录A 练习问题的解答 附录B Java的内存模型 附录C Java线程的优先级 附录D 线程相关的主要API 附录E 参考文献
Mastering Immutable.js 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
immutability-util:一个开源 immutable data 的轮子
前端开源库-immutable-ai不可变人工智能,不可变核心的可选接口
Immutable详解及React中实践.pdf
Immutable Collections Library for Kotlin Immutable collection interfaces and implementation prototypes for Kotlin. For further details see the proposal. Prototype implementation is based on ...
go-immutable-radix, 在Golang中,一个不可变的基数树实现 go-immutable-radix 提供实现不可变 radix的iradix 包。 包只提供单个 Tree 实现,针对稀疏节点优化。作为一个基数树,它提供以下内容:O(k) 操作。在许多...
Mastering Immutable PDF Mastering Immutable epub Mastering Immutable azw3 示例源码
react面试题 react_react面试题之对immutable的理解
不可变视图-其他集合对象的不可变视图概述immutable-views包提供的集合类是其他(可变)集合对象上的不可变视图: 另一个映射对象的不可变视图。 在另一个列表(序列)对象上的变视图。 在另一个set对象上的变视图。...
不可变的 不变的MongoDB。 该库是NodeJS mongodb API的直接替换方法的集合,这些方法允许mongodb用作不可变数据库。 实现是幼稚的,并且不强制执行锁定,而Mongo仅在文档级别上支持该锁定。 它尚未在生产中经过测试...
Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了...
提供一个抽象的ImmutableCollection类,该类扩展(并限制了)SplFixedArray类,并提供(派生的)不可变集合类具有行为逻辑的多个特征。 为什么用这个 常规的php“数组”根本不是数组,而是经过排序的哈希图。 它们...
不可变的角度 支持在 Angular 1.x 中查看和枚举集合 ... import Immutable from 'immutable' ; class SomethingController { static get $inject ( ) { return [ '$scope' ] ; } constructor ( $