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

我们可以不必通过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. python学习之旅(六)

    Python基础知识(5):基本数据类型之字符串(Ⅱ) 字符串方法 17.join:对字符串进行拼接 x="can" y="li" y.join(x) 结果: ...

  2. 软件毕业设计文档流程与UML图之间的关系

    每个模型都是用一种或者多种UML图来描述的,映射关系如下: 1.用例模型:使用用例图.顺序图.通信图.活动图和状态图来描述. 2.分析模型:使用类图和对象图(包括子系统和包).顺序图(时序图).通信图 ...

  3. nginx获取uri里面的参数

    add_header Content-Disposition "attachment;fileName=$arg_filename"; 请求连接为:10.26.1.165/abc? ...

  4. C++/C面试题

    (1) 按位运算只适用于字符型和整数型变量以及它们的变体,对其他数据类型不适用: (2) 一般在打开网页时,需要在浏览器中输入网址,因此,需要通过网址找到访问资源的 IP 地址,从而可以把请求发送到对 ...

  5. swp文件已存在

    vim编辑某个文件时,提示.xxx.sh.swp文件已存在是因为异常退出后,linux会生成一个swp文件,无论选择什么,下次进入还是会提示ll 命令无法看到文件使用 rm -rf .xxx.sh.s ...

  6. 20175320 2018-2019-2 《Java程序设计》第3周学习总结

    20175320 2018-2019-2 <Java程序设计>第3周学习总结 教材学习内容总结 本周学习了教材的第四章的内容.在这章中介绍了面向对象编程的概念以及Java编程中的类与对象, ...

  7. 部署WEB项目到服务器(四)部署WEB项目Forum到linux服务器(Ubuntu)详解

    突发奇想,想在自己电脑上部署一个web网站. 1,使用Navicat for MYSQL客户端创建WEB项目数据库: Navicat for MYSQL连接虚拟机中的mysql数据库 启动mysql数 ...

  8. LeetCode 993 Cousins in Binary Tree 解题报告

    题目要求 In a binary tree, the root node is at depth 0, and children of each depth k node are at depth k ...

  9. 对Java代码加密的两种方式,防止反编译

    使用Virbox Protector对Java项目加密有两种方式,一种是对War包加密,一种是对Jar包加密.Virbox Protector支持这两种文件格式加密,可以加密用于解析class文件的j ...

  10. react 中的return 什么时候用小括号,什么时候用大括号啊

    return( <div>....</div> ) return( <Component/> ) return{...} 1:html 2:react 组件 3:j ...