浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象

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

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

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

 1 public class ClassContainerOne {
 2     private static Map<String, Object> container = new HashMap<>();
 3
 4     public static void addClass(String name,Object value){
 5         container.put(name,value);
 6     }
 7     public static Object getClass(String name){
 8         return container.get(name);
 9     }
10 }

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

 1 public class Test {
 2     public static void main(String[] args) {
 3         Teacher teacher = new Teacher("A老师");
 4         Student student = new Student("B学生");
 5         ClassContainerOne.addClass("teacher",teacher);
 6         ClassContainerOne.addClass("student",student);
 7         Teacher teacher1 = (Teacher) ClassContainerOne.getClass("teacher");
 8         Student student1 = (Student)ClassContainerOne.getClass("student");
 9         System.out.println(teacher1 + " " + student1);
10     }
11 }

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

 1 public class ClassContainerTwo {
 2     private static Map<Class<?>, Object> container = new HashMap<>();
 3
 4     public static <T> void addClass(Class<T> valueType,T value) {
 5         container.put(valueType, value);
 6     }
 7
 8     public static <T> T getClass(Class<T> valueType) {
 9         return valueType.cast(container.get(valueType));
10     }
11 }

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

 1 public class Test {
 2     public static void main(String[] args) {
 3         Teacher teacher = new Teacher("A老师");
 4         Student student = new Student("B学生");
 5         ClassContainerTwo.addClass(Teacher.class,teacher);
 6         ClassContainerTwo.addClass(Student.class,student);
 7         Teacher teacher1 = ClassContainerTwo.getClass(Teacher.class);
 8         Student student1 = ClassContainerTwo.getClass(Student.class);
 9         System.out.println(teacher1 + " " + student1);
10     }
11 }

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

 1 public class Key<T> {
 2     private String name;
 3     private Class<T> valueType;
 4
 5     public Key(String name, Class<T> valueType) {
 6         this.name = name;
 7         this.valueType = valueType;
 8     }
 9
10     /**
11      * 同时重写equals()和hashCode(),避免加入类容器是和
12      * 从类容器中取出对象时实例化的key不是同一个对象,及类属性相同,但是地址不同
13      */
14     @Override
15     public boolean equals(Object o) {
16         if (this == o) return true;
17         if (o == null || getClass() != o.getClass()) return false;
18         Key<?> key = (Key<?>) o;
19         return Objects.equals(name, key.name) &&
20                 Objects.equals(valueType, key.valueType);
21     }
22
23     @Override
24     public int hashCode() {
25         return Objects.hash(name, valueType);
26     }
27
28     public Class<T> getValueType() {
29         return valueType;
30     }
31 }

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

 1 public class ClassContainerThree {
 2     private static Map<Key<?>,Object> container = new HashMap<>();
 3
 4     public static <T> void addClass(Key<T> key,T value) {
 5         container.put(key, value);
 6     }
 7
 8     public static <T> T getClass(Key<T> key) {
 9         return key.getValueType().cast(container.get(key));
10     }
11 }

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

 1 public class Test {
 2     public static void main(String[] args) {
 3         Teacher teacher = new Teacher("A老师");
 4         Student student = new Student("B学生");
 5         ClassContainerThree.addClass(new Key<>("teacher",Teacher.class),teacher);
 6         ClassContainerThree.addClass(new Key<>("teacher",Student.class),student);
 7         Teacher teacher1 = ClassContainerThree.getClass(new Key<>("teacher",Teacher.class));
 8         Student student1 = ClassContainerThree.getClass(new Key<>("teacher",Student.class));
 9         System.out.println(teacher1 + " " + student1);
10     }
11 }

原文地址:https://www.cnblogs.com/skykuqi/p/11246765.html

时间: 2024-08-01 13:07:26

浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象的相关文章

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

1 工厂模式简介 工厂模式的定义:简单地说,用来实例化对象,代替new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式可以动态决定将哪一个类实例化,不用先知道每次要实例化哪一个类. 工厂模式可以分一下三种形态: 简单工厂 (Simple Factory)模式:又称静态工厂模式(StaticFactory). 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory). 抽象工厂 (Abstract Factroy)模式:又称工具箱模式

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

1 工厂方法模式简介 工厂方法 (Factroy Method) 模式:又称多态性工厂模式(Polymorphic Factory),在这种模式中,核心工厂不再是一个具体的类,而是一个抽象工厂,提供具体工厂实现的接口,具体创建产品交由子工厂去做,抽象工厂不涉及任何产品被实例化的细节.而不同等级的产品,就对应一个不同等级的工厂,如下图. 图1 1.1工厂方法模式(多态性工厂模式): 工厂方法模式有三个角色: 1. 抽象产品接口 2. 具体产品类 3. 抽象工厂接口 4.具体工厂类. 1.2工厂方法

浅析JAVA设计模式之工厂模式(三)

在阅读本文之前,请先阅读(一)和(二)中的简单工厂模式和工厂方法模式. 1抽象工厂模式简介 抽象工厂 (Abstract Factroy) 模式:工具箱模式(kit).抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态,如下图. 图1.1 上图左边有一个工厂类的等级结构,右边有两个不同的产品等级结构,分别是产品A的等级结构和产品B的等级结构,工厂1和工厂2分别负责不同一个产品等级,同一个产品族的产品的生产.又例如下图: 图1.2 上图表示的是Button和Text两个不同产品的等级

浅析JAVA设计模式(一)

第一写技术博客,只是想把自己一天天积累的东西与大家分享.今天在看<大型网站架构和java中间件>这本书时,其中提到代理模式的动态代理.作为java中间件的一个重要基础,我觉的有必要整理和分析下java的23种设计模式,如有不对的地方,请大家留贴指正. 一.设计模式的分类 总体来说,Java的设计模式分为三个大类(创建型模式.结构型模式.行为型模式) 创建型模式:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式:适配器模式.装饰模式.代理模式.外观模式(又称门面模式).桥

Java 类型安全的异构容器

转载自:http://blog.csdn.net/sh_c1991/article/details/45965743 我们的想法是用key自身的class 类型作为key.因为Class 是参数化的类型,它可以确保我们使Context方法是类型安全的,而无需诉诸于一个未经检查的强制转换为T.这种形式的一个Class 对象称之为类型令牌(type token). [java] view plain copy public class Context { private final Map<Clas

浅析JAVA设计模式(二)

2. 里氏替换原则:LSP(Liskov Substitution Principle)里氏替换原则,定义为只要父类出现的地方子类就可以出现,而且用子类替换后,程序也不会出现问题,使用者根本不用关心是父类还是子类.这也是我们java继承特性的一个表现. 下面用个实际项目中遇到的一个简单的需求:现在有A类产品需要调用method1(),B类产品也需要调用method(),同样C类产品也需要调用method(),但是我们需要直接让D这个人去处理这个Method(),那么我们可以这样设计一个抽象类Ab

浅析JAVA设计模式(三)

4.接口隔离原则: ISP(Interface Segregation Principle)  客户端不应该依赖它不需要的接口,或者说类的依赖的关系应该建立在最小的接口上.举个例子,直接上代码: 1 interface I {  2     public void method1();  3     public void method2();  4     public void method3();  5     public void method4();  6     public vo

浅析JAVA设计模式之单例模式(一)

1 单例模式简介 单例模式确保一个类只有一个实例,并且自行实行实例化并向整个系统提供这个实例. 单例模式有三个要点: 1.某个类只能有一个实例. 2.它必须自行创建这个实例. 3.它必须向整个系统提供这个实例. 单例模式主要分为两种:饿汉式单例模式和懒汉式单例模式 1.1饿汉式单例模式: 饿汉式单例模式是java语言实现起来最为简单的单例模式,UML图如下: 图1.1 从图中可以看出,它自己将自己实例化. 1.2饿汉式单例模式的实现(建一个Singleton包,所有程序放在该包下): (1)建一

浅析Java设计模式 - 单例模式

以下是三种单例模式的代码实现,前两者用的比较多 (言外之意 最后一种可以忽略) 1 package com.signle; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 /** 7 * 8 * @title 单例模式 9 * @Copyright Copyright (c)2016年3月9日 10 * @Company CTC 11 * @version 1.0 12 * @author ejokovic 13 * @time