最近在着手重构一个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设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象的更多相关文章

  1. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  2. 浅析JAVA设计模式之工厂模式(二)

    1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...

  3. 浅析JAVA设计模式(一)

    第一写技术博客,只是想把自己一天天积累的东西与大家分享.今天在看<大型网站架构和java中间件>这本书时,其中提到代理模式的动态代理.作为java中间件的一个重要基础,我觉的有必要整理和分 ...

  4. 阿里架构师浅析Java设计模式之虚拟代理模式

    虚拟代理模式(Virtual Proxy)是一种节省内存的技术,它建议创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候.在特定的应用中,不同部分的功能由不同的对象组成,应用启动 ...

  5. 浅析JAVA设计模式(三)

    4.接口隔离原则: ISP(Interface Segregation Principle)  客户端不应该依赖它不需要的接口,或者说类的依赖的关系应该建立在最小的接口上.举个例子,直接上代码:  1 ...

  6. 浅析JAVA设计模式(二)

    2. 里氏替换原则:LSP(Liskov Substitution Principle)里氏替换原则,定义为只要父类出现的地方子类就可以出现,而且用子类替换后,程序也不会出现问题,使用者根本不用关心是 ...

  7. 重学 Java 设计模式:实战备忘录模式「模拟互联网系统上线过程中,配置文件回滚场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 实现不了是研发的借口? 实现不了,有时候是功能复杂度较高难以实 ...

  8. 浅析Java 泛型

    泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...

  9. 面试准备——java设计模式

    1 总体来说,设计模式分为三大类: 设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案. 创建型模式(五种):工厂方法模式.抽象工厂模式.单例模式. ...

随机推荐

  1. P2469 [SDOI2010]星际竞速(费用流)

    P2469 [SDOI2010]星际竞速 最小路径覆盖问题 每个星球必须恰好去一次,而每次高速航行都是从一个星球到另一个星球. 那么高速航行的起点可以保证被去过 高速航行和空间跳跃可以是互相独立的 将 ...

  2. Mybatis-技术专区-中的条件查询createCriteria example里面的条件

    之前用Mybatis框架反向的实体,还有实体里面的Example,之前只是知道Example里面放的是条件查询的方法,可以一直不知道怎么用,到今天才开始知道怎么简单的用. 在我们前台查询的时候会有许多 ...

  3. Problems occurred when invoking code from plug-in: "org.eclipse.jface".

    java.lang.NullPointerException at com.genuitec.eclipse.easie.core.AppServer.getServerLabel(Unknown S ...

  4. yara规则的二进制漏洞

    https://www.anquanke.com/post/id/147675 yara32.exe 后缀.yar

  5. AngularJs双向绑定

    模型数据(Data) 模型是从AngularJS作用域对象的属性引申的.模型中的数据可能是Javascript对象.数组或基本类型,这都不重要,重要的是,他们都属于AngularJS作用域对象. An ...

  6. Sass函数:值列表函数length

    length() 函数主要用来返回一个列表中有几个值,简单点说就是返回列表清单中有多少个值: >> length(10px) 1 >> length(10px 20px (bo ...

  7. java两个引用指向同一个对象

  8. [BZOJ4316]小C的独立集 仙人掌?

    题目链接 因为xls让我每周模拟一次,然后学习模拟中没有学过的东西.所以就来学圆方树. 本来这道题用不着圆方树,但是圆方树是看yyb的博客学的,他在里面讲一下作为一个引子,所以也来写一下. 首先来Ta ...

  9. boost IOStreams

    Boost.IOStreams provides numerous implementations of the two concepts. Devices which describes data ...

  10. git常用操作命令1

    1. 本地库初始化操作 命令: git init 效果: Initialized empty Git repository in E:/ws/git/ws/.git/ 会在当前目录(E:/ws/git ...