上一篇讲的是容器工厂的原型。

我们可以不必通过new关键之创建实例,可以直接取容器里面的实例。

我们可以发现,在对比他们的地址值的时候,他们是相同的为true。

如果我们需要的是不一样的呢。也就是有一些特殊的操作需要到的是单例地址。

下面让我们看看如何创建一个可以随意切换原型&单例的容器工厂吧。

我们在上一篇原型的容器工厂上稍微做一下改造就OK了!

添加一个描述bean的类,封装了配置文件bean的类

public class Definition {
//bean的唯一标识
private String id;
//bean的完整类名
private String className;
//bean的创建方式
private String scope = "singleton"; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getClassName() {
return className;
} public void setClassName(String className) {
this.className = className;
} public String getScope() {
return scope;  
} public void setScope(String scope) {
this.scope = scope;
}
}

第二,我们需要在容器工厂的类里面做出稍稍的改动。

如下:

public class ContainerFactoryTwo {
//单例的容器(Singleton)
private static Map<String,Object> singleton = new HashMap<String,Object>(); //原型的容器(prototype)
private static Map<String,Definition> prototype = new HashMap<String,Definition>(); //初始化
public ContainerFactoryTwo(String resourcePath){
initPrototype(resourcePath);
initSingleton();
} public void initPrototype(String resourcePath){
//创建SAX解析器
SAXReader reader = new SAXReader(); try {
Document document = reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath));
Element root = document.getRootElement();
List<Element> list = root.elements();
for (Element e:list){
String id = e.attributeValue("id");
String className = e.attributeValue("class");
String scope = e.attributeValue("scope");
//构建bean的定义
Definition def = new Definition();
def.setId(id);
def.setClassName(className);
if(scope!=null){
def.setScope(scope);
}
prototype.put(id,def);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 初始化单利容器
*/ private void initSingleton(){
//遍历prototype里面的值做出判断
for (String key : prototype.keySet()) {
Definition def = prototype.get(key);
//如果是判断是否是singleton
if("singleton".equals(def.getScope())){
try {
//将实例化对象保存到singleton的map里
singleton.put(key, Class.forName(def.getClassName()).newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
public Object getBean(String name){
return getContainerBean(name);
} public <T> T getBean(String name, Class<T> clazz){
return (T)getContainerBean(name);
} private Object getContainerBean(String name){
//获取作用域属性
String scope = prototype.get(name).getScope();
try {
//三目运算,singleton在scope里面?是的话就之前前者(K对应的已经是一个Object对象)否则执行后者,通过类加载返回一个对象
return ("singleton".equals(scope))?singleton.get(name):
Class.forName(prototype.get(name).getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
} }

测试:

public class Main {
public static void main(String[] args) {
//创建工厂
ContainerFactoryTwo factory = new ContainerFactoryTwo("beans.xml"); Phone phone1 = factory.getBean("OppoPhone", Phone.class);//singleton
Phone phone2 = factory.getBean("OppoPhone", Phone.class);//singleton Pad pad1 = (Pad) factory.getBean("OppoPad", Pad.class);//prototype
Pad pad2 = (Pad) factory.getBean("OppoPad", Pad.class);//prototype
System.out.println(phone1==phone2);
System.out.println(pad1==pad2);
//phone1.call();
}
}

结果为:

true

false

注意:在XML文件里面的scope

决定单例或者是原型容器在于Map

容器工厂(原型&单例)的更多相关文章

  1. OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式

    在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...

  2. Spring容器-ApplicationContext的单例设计

    Spring容器-ApplicationContext的单例设计   每次通过new创建一个ApplicationContext容器,都会执行refresh方法,看源代码了解到这个refresh方法会 ...

  3. 初探Java设计模式1:创建型模式(工厂,单例等)

    Java 设计模式 一直想写一篇介绍设计模式的文章,让读者可以很快看完,而且一看就懂,看懂就会用,同时不会将各个模式搞混.自认为本文还是写得不错的,花了不少心思来写这文章和做图,力求让读者真的能看着简 ...

  4. C#中的简单工厂和单例

    下面首先来说说简单工厂 举个例子: 首先是父类 public abstract class Pizza { public abstract string Info(); } } 子类 public c ...

  5. 我心中的核心组件(可插拔的AOP)~第十五回 我的日志组件Logger.Core(策略,模版方法,工厂,单例等模式的使用)

    回到目录 之前的讲过两篇关于日志组件的文章,分别是<第一回  日志记录组件之自主的Vlog>和<第三回  日志记录组件之log4net>,而今天主要说一下我自己开发的另一种日志 ...

  6. Java-马士兵设计模式学习笔记-工厂模式-单例及多例

    一.单例的作用是用于控制类的生成方式,而不让外部类任意new对象 1.Car.java import java.util.ArrayList; import java.util.List; publi ...

  7. spring容器bean的作用域 & spring容器是否是单例的一些问题

    Spring容器中Bean的作用域 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...

  8. 【spring容器bean的作用域+spring容器是否是单例的一些问题】

    Spring容器中Bean的作用域 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...

  9. php设计模式 工厂、单例、注册树模式

    Source Code Pro字体  easyphp 命名空间:隔离类和函数,php5.3以后 //test5.php<?php namespace Test5;//命名空间必须是程序脚本的第一 ...

随机推荐

  1. js中级小知识1

    首先我们复习之前的小知识,本期博客与之前有关 js数据类型 基本数据类型:string    undefined         null         boolean          numbe ...

  2. python全栈开发 * 01知识点汇总 * 180530

    一 python简介. 1.创始人:  吉多 .范罗苏姆  \   (Guido van Rossum). 2.时间  :  1989年. 3.主要应用领域  :  云计算 \  WEB开发  \   ...

  3. day20 二十、加密模块、操作配置文件、操作shell命令、xml模块

    一.加密模块 1.hashlib模块:加密 ①有解密的加密方式 ②无解密的加密方式:碰撞检查 -- 1)不同数据加密后的结果一定不一致 -- 2)相同数据的加密结果一定是一致的 import hash ...

  4. 15 个 Android 通用流行框架大全(转载)

    1. 缓存 DiskLruCache    Java实现基于LRU的磁盘缓存 2.图片加载 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库 Picas ...

  5. 解决Kettle ETL数据乱码

    首先用insert语句插入一条数据试试是否因为MySQL编码不对引起,如果是MySQL原因,修改MySQL编码即可: 如果不是因为MySQL的编码导致问题,那么在Kettle的表输出中,编辑连接-选项 ...

  6. Redis入门到高可用(十六)—— 持久化

    一.持久化概念 二.持久化方式 三.redis持久化方式之——RDB 1.什么是RDB 在 Redis 运行时, RDB 程序将当前内存中的数据库快照保存到磁盘文件中, 在 Redis 重启动时, R ...

  7. C#基础加强(4)之秒懂IL、CTS、CLS和CLR

    IL(Intermediate Language) 中间语言..Net 平台下不只有 C# 语言,还有 VB.Net.F# 等语言.IL 是程序最终编译的可执行二进制代码(托管代码),类似于 Java ...

  8. CentOS 7 下使用yum安装MySQL5.7.20

    CentOS7默认数据库是mariadb, 但是 好多用的都是mysql ,但是CentOS7的yum源中默认好像是没有mysql的. 上一篇安装的是5.6的但是我想安装5.7的  yum安装是最简单 ...

  9. python进阶(三) 内建函数getattr工厂模式

    getattr()这个方法最主要的作用是实现反射机制.也就是说可以通过字符串获取方法实例.  传入不同的字符串,调用的方法不一样. 原型:getattr(对象,方法名) 举个栗子: pyMethod类 ...

  10. WxWidgets笔记

    关于环境变量的配置:解压wxwidgets的压缩包之后要新建名为 WXWIN 的环境变量,变量的值为 解压得到的目录,不知为何要使用此环境变量 编译时使用的命令:mingw32-make -j1 -f ...