浅析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)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案. 创建型模式(五种):工厂方法模式.抽象工厂模式.单例模式. ...
随机推荐
- Windows下anaconda安装opencv
win+R打开cmd界面,输入conda create -n opencv python=3.6,创建名为opencv的虚拟空间,然后一路y,直到安装完成. activate opencv 然后输入 ...
- spring(六):spring中AOP的基本使用
AOP:面向切面编程[底层使用动态代理实现],就是在运行期间动态的将某段代码切入到方法的指定位置进行运行的编程方式 基本使用 使用AOP功能需要引入spring的aop以及aspects相关包 < ...
- FY20-ASE 开课!
自我介绍 我叫陈志锴,undergraduate,pre-phd,初级程序员(c++和c的区别只知道多了类和对象这种,python只会写大作业代码和用基础的neural network框架),曾经跟着 ...
- ActiveMQ修改端口号
1.修改tcp端口号 安装目录下的conf/activemq.xml 2.修改管理页面的访问端口号 安装目录下的conf/jetty.xml
- robotframework的if else
- canvas 绘制三次贝塞尔曲线
代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...
- Java字节缓冲流和字符缓冲流学习
1.字节缓冲流 首先要明确一个概念:对文件或其他目标频繁的读写操作,效率低,性能差. 使用缓冲流的好处是,能够高效的读写信息,原理是将数据先缓冲起来,然后一起写入或者读取出来. BufferedInp ...
- 【锁】synchronized的实现(偏向锁、轻量级锁、重量级锁)
synchronized的三种应用方式 一. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁. 二. 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁. 三. ...
- selenium环境搭建,浏览器驱动安装
一安装Python: 1.下载Phtyon地址:https://www.python.org/getit/ 2.安装python会默认安装两个基础包setuptools,pip 也可以手动安装: ...
- vue循环渲染变量类样式
由于需求的需要,将五种不同的颜色样式通过v-for进行遍历渲染,所以我这里采用绑定类函数进行判断方式.代码: 效果: 灵感来自:https://www.jianshu.com/p/33e181be3d ...