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

我们可以不必通过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. HttpRequest获得服务端和客户端的详细信息

    参考文档:http://blog.csdn.net/u012104100/article/details/43051301 http://blog.csdn.net/u011162260/articl ...

  2. ThinkPHP缓存技术(S(),F(),查询缓存,静态缓存)

    直接查看原网址 https://blog.csdn.net/u010081689/article/details/47976271

  3. mui 事件管理及自定义事件详解

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  4. css的小知识3

    1.补充 margin的margin:0 auto:会解决元素的居中,前提是给这个元素设置width 2.css的层叠问题 css有两个性质 1.继承性 2.层叠性  选择器的一种选择能力,谁的权重大 ...

  5. BASE64和图片之间的互相转换

    package com.test.demo; import java.io.FileInputStream; import java.io.FileOutputStream; import java. ...

  6. rocketMQ安装部署详细解析

    近来研究了Apache开源项目rocketMQ(原为阿里项目),并在两台linux服务器上完成了部署,现在整理下,供大家参考学习. 一.简介rocketMQRocektMQ是阿里巴巴在2012年开源的 ...

  7. luogu2839 [国家集训队]middle

    题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排 ...

  8. MongoDB 备份(mongodump)与恢复(mongorestore)

    MongoDB  备份(mongodump)与恢复(mongorestore) 备份:使用mongodump命令导出所有数据库到指定目录 参数说明: --host:MongoDB所在服务器IP. -- ...

  9. 家庭记账本之微信小程序(二)

    在网上查阅了资料后,了解到了在完成微信小程序之前要完成注册阶段的工作,此次在这介绍注册阶段的流程. 1.首先你要确定小程序的定位.目的以及文案资料等(准备工作). 2.打开微信公众平台官网,点击右上角 ...

  10. 15.IEnumerable和IEnumerator

    先说IEnumerable,我们每天用的foreach你真的懂它吗? 阅读目录 自己实现迭代器 yield的使用 怎样高性能的随机取IEnumerable中的值 我们先思考几个问题: 为什么在fore ...