最近在着手重构一个java UI桌面项目,发现这个项目在一开始的时候由于需求不明确,以及开发人员对swing框架不熟悉等问题造成了页面代码混乱的情况:为了能够在各个类里都可以拿到其他类的引用去进行相应的页面响应操作,在每一个类的构造方法中都传入了主类的引用,在主类中提供了所有类的get()方法,这样的做法显得十分的臃肿,就像这样:

打开主页面后会显示窗体B,窗体B的按钮支持我们打开窗体A,窗体A按钮支持修改B中属性.我们只能通过在主页面的类中使用get(),set()方法来持有A和B的引用,在A和B的构造方法中提供主页面的引用,从而才能做到在B中调用A,A中调用B.但是这样的做法随着项目的开展主页面的类中get()和set()方法的数量将多到你无法想象,那么是否可以提供一个容器,在创建页面时就将该页面对象存入该容器中,其他页面只需通过这个容器来获取其他页面窗体进行操作?

废话不多说我们开始干活,由于不同的页面类型即其类可能不同所以我们提供的容器需要是Object的:

 public class ClassContainerOne {
private static Map<String, Object> container = new HashMap<>(); public static void addClass(String name,Object value){
container.put(name,value);
}
public static Object getClass(String name){
return container.get(name);
}
}

简单的封装一下我们就可以正常使用,这样的操作,我们只能依靠String来区分对象并且自己来完成强制类型转换:

 public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher("A老师");
Student student = new Student("B学生");
ClassContainerOne.addClass("teacher",teacher);
ClassContainerOne.addClass("student",student);
Teacher teacher1 = (Teacher) ClassContainerOne.getClass("teacher");
Student student1 = (Student)ClassContainerOne.getClass("student");
System.out.println(teacher1 + " " + student1);
}
}

我想大家都会想到一个问题,那就是这样的操作安全吗?显然是否定的,一旦我们强制转换错误,那系统就会崩溃,因此我们用泛型来修改完善我们的容器类:

 public class ClassContainerTwo {
private static Map<Class<?>, Object> container = new HashMap<>(); public static <T> void addClass(Class<T> valueType,T value) {
container.put(valueType, value);
} public static <T> T getClass(Class<T> valueType) {
return valueType.cast(container.get(valueType));
}
}

我们转为使用其Class类型作为key值来对应我们的对象,确实可以做到对象获取时的万无一失:

 public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher("A老师");
Student student = new Student("B学生");
ClassContainerTwo.addClass(Teacher.class,teacher);
ClassContainerTwo.addClass(Student.class,student);
Teacher teacher1 = ClassContainerTwo.getClass(Teacher.class);
Student student1 = ClassContainerTwo.getClass(Student.class);
System.out.println(teacher1 + " " + student1);
}
}

但是这样做的代价就是我们无法存放多个相同的对象,我们可以创建一个钩子类来衔接这个类容器和各个对象:

 public class Key<T> {
private String name;
private Class<T> valueType; public Key(String name, Class<T> valueType) {
this.name = name;
this.valueType = valueType;
} /**
* 同时重写equals()和hashCode(),避免加入类容器是和
* 从类容器中取出对象时实例化的key不是同一个对象,及类属性相同,但是地址不同
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key<?> key = (Key<?>) o;
return Objects.equals(name, key.name) &&
Objects.equals(valueType, key.valueType);
} @Override
public int hashCode() {
return Objects.hash(name, valueType);
} public Class<T> getValueType() {
return valueType;
}
}

然后继续完善我们的类容器:

 public class ClassContainerThree {
private static Map<Key<?>,Object> container = new HashMap<>(); public static <T> void addClass(Key<T> key,T value) {
container.put(key, value);
} public static <T> T getClass(Key<T> key) {
return key.getValueType().cast(container.get(key));
}
}

这样的封装,虽然对于Key的实例化代码较长,但是很好的解决了我们的类容器存储和获取问题:

 public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher("A老师");
Student student = new Student("B学生");
ClassContainerThree.addClass(new Key<>("teacher",Teacher.class),teacher);
ClassContainerThree.addClass(new Key<>("teacher",Student.class),student);
Teacher teacher1 = ClassContainerThree.getClass(new Key<>("teacher",Teacher.class));
Student student1 = ClassContainerThree.getClass(new Key<>("teacher",Student.class));
System.out.println(teacher1 + " " + student1);
}
}

最新文章

  1. HomeWork2
  2. IOS基础之 (四) OC对象
  3. Linux下配置Hadoop 1.2.1
  4. 1020: 部分A+B
  5. Fragstats景观分析研究
  6. Terminating app due to uncaught exception &#39;NSUnknownKeyException&#39;, reason: xxxx
  7. 动态的改变标签内的src属性
  8. Fail2防止sshd暴力破解
  9. 【1414软工助教】团队作业7——Alpha冲刺之事后诸葛亮 得分榜
  10. 瞎j8封装第二版之数据层的封装
  11. Java中的volatile的作用和synchronized作用
  12. 会声会影小成果分享(那段青春岁月)——校学习部宣传视频制作&amp;生日祝福
  13. 《JavaScript高级程序设计》笔记:客户端检测(九)
  14. tomcat端口冲突,关闭端口方法
  15. static 关键字的作用
  16. Redis数据类型-Strings
  17. Redis都有哪些数据类型
  18. 在mvc4中多语言建站的实例
  19. [Offer收割]编程练习赛15 A.偶像的条件[贪心]
  20. [转载]解决flash与js交互、flash跨域交互、flash跨域提交

热门文章

  1. 在vue中设计一个客户签名的功能
  2. WEEX-EROS开发小笔记
  3. smbumount - 为普通用户卸载smb文件系统
  4. windows server 2008R2 配置tomcat服务开机自启动
  5. OtterCTF - Reverse - Msg Me This
  6. HTML 地理定位 的实例
  7. LINUX Mysql5.6.19 安装
  8. Java中实现线程同步的三种方法
  9. Linux自用指令——2019年10月23日
  10. 向指定URL 发送POST请求的方法