浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象
最近在着手重构一个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);
}
}
浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象的更多相关文章
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- 浅析JAVA设计模式之工厂模式(二)
1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...
- 浅析JAVA设计模式(一)
第一写技术博客,只是想把自己一天天积累的东西与大家分享.今天在看<大型网站架构和java中间件>这本书时,其中提到代理模式的动态代理.作为java中间件的一个重要基础,我觉的有必要整理和分 ...
- 阿里架构师浅析Java设计模式之虚拟代理模式
虚拟代理模式(Virtual Proxy)是一种节省内存的技术,它建议创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候.在特定的应用中,不同部分的功能由不同的对象组成,应用启动 ...
- 浅析JAVA设计模式(三)
4.接口隔离原则: ISP(Interface Segregation Principle) 客户端不应该依赖它不需要的接口,或者说类的依赖的关系应该建立在最小的接口上.举个例子,直接上代码: 1 ...
- 浅析JAVA设计模式(二)
2. 里氏替换原则:LSP(Liskov Substitution Principle)里氏替换原则,定义为只要父类出现的地方子类就可以出现,而且用子类替换后,程序也不会出现问题,使用者根本不用关心是 ...
- 重学 Java 设计模式:实战备忘录模式「模拟互联网系统上线过程中,配置文件回滚场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 实现不了是研发的借口? 实现不了,有时候是功能复杂度较高难以实 ...
- 浅析Java 泛型
泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...
- 面试准备——java设计模式
1 总体来说,设计模式分为三大类: 设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案. 创建型模式(五种):工厂方法模式.抽象工厂模式.单例模式. ...
随机推荐
- LayaBox 常用技巧
1.修改IDE的菜单 找到安装路径的LayaAirIDE\resources\app\out\vs\layaEditor\renders\laya.editorUI.xml 注意事项: 1.mask的 ...
- Fiddler查看IP和响应时间
原文:Fiddler查看IP和响应时间 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/si ...
- java Activiti6.0 后台 框架 spring5 SSM 工作流引擎 审批流程
1.模型管理 :web在线流程设计器.预览流程xml.导出xml.部署流程 2.流程管理 :导入导出流程资源文件.查看流程图.根据流程实例反射出流程模型.激活挂起 3.运行中流程:查看流程信息.当前任 ...
- 实现combobox模糊查询的时候报错 InvalidArgument=“0”的值对于“index”无效
因为要对combobox实现模糊查询,因为系统实现的匹配只能从左到右进行匹配,所以利用两个list来进行模糊匹配,主要代码如下: List<string> listOnit = new L ...
- webstorm2018
1.安装后修改hosts: windows\system32\drivers\etc 管理员权限修改 0.0.0.0 account.jetbrains.com 2. 选择activation c ...
- linux改变内核参数
- javaweb各种框架组合案例(五):springboot+mybatis+generator
一.介绍 1.springboot是spring项目的总结+整合 当我们搭smm,ssh,ssjdbc等组合框架时,各种配置不胜其烦,不仅是配置问题,在添加各种依赖时也是让人头疼,关键有些jar包之间 ...
- HDU-5378 概率DP
题意:给定一棵有n个节点的树,现在要给节点附1~n的权值(各节点权值不能相同),一棵子树的领袖就是子树中权值最大的节点,问有多少种分配方案使得最后有恰好K个领袖. 解法:这道题一看以为是树上的计数问题 ...
- Django--Auth模块使用
1.Auth模块介绍 1.1 Auth模块是Django自带的用户认证模块,用于处理用户账户.群组.许可和基于cookie的用户回话 Django的认证系统主要包括下面几个部分 1.用户 2.许可 3 ...
- [ES6]react中使用es6语法
前言 不论是React还是React-native,facebook官方都推荐使用ES6的语法,没在项目中使用过的话,突然转换过来会遇到一些问题,如果还没有时间系统的学习下ES6那么注意一些常见的写法 ...