一、什么是简单工厂模式

设计模式的核心是“分工”,通过分工将对象与职责划分的更细化,进而提升系统设计的可扩展性,使其更容易维护。

开闭原则:对扩展开放,对修改关闭;要增加一个新的处理逻辑,可以开一个新的类,不要在老的上面修改

依赖倒转原则:依赖关系从具体转向抽象,也就是说:A调用B,不是直接调用B的实现,而是依赖B的接口

迪米特法则:类尽量少的与其他类发生关系,或者产生依赖,以此来使扩展可以更容易

工厂模式中的三种:简单工厂模式、工厂方法模式、抽象工厂模式;实现了创建者和调用者的分离,调用者不需要知道具体的创建者是什么类,只需要知道工厂的接口以及自己想要的产品名称,就可以进行调用得到想要的产品

简单工厂模式:简单工厂模式也称为静态工厂模式,工厂类一般采用静态方法,根据接收的参数不同来确定返回对象实例,但简单工厂模式违反了开闭原则,要增加一个新的类别必须要修改代码

注意,简单工厂模式就是:针对一个项目或者一个独立模块只有一个工厂类,而工厂方法模式是有一组实现了相同接口的工厂类(虽然符合开闭原则,但是会增加新的类来扩展,看情况而定,实际上在项目开发中通常还是用简单工厂比较多)

二、依据Spring中的BeanFactory自己实现简版

首先是,先写一个接口类,BeanFactory的接口类如下:

public interface BeanFactory {
    Object getBean(String beanName);
}

下面是xml配置文件 springtest.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans>

    <bean id="usertest" class="beanfactory.demo.User">

        <property name="username" value="lxlx" />

        <property name="passWord" value="111" />

        <property name="age" value="11"/>

    </bean>

</beans>

下面是bean定义的class文件 User类:

public class User {
private String username;
private String passWord;
private int age; public void setUsername(String username) {
this.username = username;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
} public void setAge(int age) {
this.age = age;
} public String getUsername() {
return username;
} public String getPassWord() {
return passWord;
} public int getAge() {
return age;
}
}

接下来是实现类 ConcreteBeanFactory:

package beanfactory.demo;

import org.dom4j.io.SAXReader;

import org.dom4j.*;

import java.io.File;

import java.lang.reflect.Type;

import java.util.HashMap;

import java.util.Map;

import java.util.Iterator;

import java.lang.reflect.Method;

/**

 * Created by xiami on 2019/5/26.

 */

public class ConcreteBeanFactory implements BeanFactory{

    private Map<String, Object> beanDefinitionMap = new HashMap<String, Object>();

    //简单工厂模式的特征是:一个工厂中可以生产多种不同的产品,这里的Bean其实是没有区分不同的bean,是可以通过get返回不同的bean

    @Override

    public Object getBean(String beanName) {

        return beanDefinitionMap.get(beanName);

    }

    //增加一个init的操作方法

    //从xml配置文件中进行解析读取

    public void init(String xmlPath){

        SAXReader saxReader = new SAXReader();

        File file = new File(xmlPath);

        try {

            Document document = saxReader.read(file);

            Element root = document.getRootElement();

            Element foo;

            // 遍历bean

            for (Iterator i = root.elementIterator("bean"); i.hasNext();) {

                foo = (Element) i.next();

                // 获取bean的属性id和class

                Attribute id = foo.attribute("id");

                Attribute cls = foo.attribute("class");

                // 利用Java反射机制,通过class的名称获取Class对象

                Class<?> bean = Class.forName(cls.getText());

                // 获取对应class的信息

                java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);

                // 获取其属性描述

                java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();

                // 设置值的方法

                Method mSet = null;

                // 创建一个对象

                Object obj = bean.newInstance();

                // 遍历该bean的property属性

                for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {

                    Element foo2 = (Element) ite.next();

                    // 获取该property的name属性

                    Attribute name = foo2.attribute("name");

                    String value = null;

                    Object typeValue = null;

                    //获取value值

                    value = foo2.attributeValue("value");

                    for (int k = 0; k < pd.length; k++) {

                        if (pd[k].getName().equalsIgnoreCase(name.getText())) {

                            mSet = pd[k].getWriteMethod();

                            //设置值这里,需要根据类型给value做类型转换

                            //properties中包含了properType的项,因为当前程序中就只有String和Int,先处理这样的类型

                            Type mType = pd[k].getPropertyType();

                            if (mType.getTypeName().equals("java.lang.String")){

                                typeValue = String.valueOf(value);

                            }

                            else if(mType.getTypeName().equals("int")){

                                typeValue = Integer.parseInt(value);

                            }

                            mSet.invoke(obj, typeValue);

                        }

                    }

                }

                // 将对象放入beanMap中,其中key为id值,value为对象

                beanDefinitionMap.put(id.getText(), obj);

            }

        }catch (Exception e){

            System.out.println(e.toString());

        }

    }

}

下面是测试类:

public class Client {

    public static void main(String[] args){

        AbstractBeanFactory absbf = new AbstractBeanFactory();

        absbf.init("E:\\java-demo\\src\\beanfactory\\demo\\springtest.xml");

        User user = (User)absbf.getBean("usertest");

        System.out.println("User类的bean有没有创建成功:" + user);

        System.out.println("属性值:" + user.getUsername() + "," + user.getPassWord() + "," + user.getAge());

    }

}

测试结果是:

要理解的是:简单工厂模式是一种思想,就是:不针对特定的产品进行工厂的划分,也就是说没有多个批次或者类别的工厂,而是所有的内容都在一个工厂里面生产,你需要什么我给你什么即可

参考文章:https://blog.csdn.net/mlc1218559742/article/details/52776160/

【Spring源码解析】—— 简单工厂模式的BeanFactory的超简版实现的更多相关文章

  1. spring源码解析——2容器的基本实现(第2版笔记)

    感觉第二版写的略潦草,就是在第一版的基础上加上了新的流行特性,比如idea,springboot,但是,潦草痕迹遍布字里行间. 虽然换成了idea,但是很多截图还是eclipse的,如果不是看了第一版 ...

  2. 【Spring源码解析】—— 委派模式的理解和使用

    一.什么是委派模式 委派模式,是指什么呢?从字面含义理解,委派就是委托安排的意思,委派模式就是在做具体某件事情的过程中,交给其他人来做,这个事件就是在我的完整链路上的一部分,但是复杂度较高的情况下或者 ...

  3. 【Spring源码解析】—— 策略模式在Spring中的应用

    一.         什么是策略模式 策略模式的定义/含义:策略本身就是为了实现某一个目标而采取的一种工作方式,因此只要能够达成目标,则采取哪一种策略都可以:因此多种实际的策略之间是相互平行的. 注意 ...

  4. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...

  5. spring 源码解析

    1. [文件] spring源码.txt ~ 15B     下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB     下载( ...

  6. Spring源码解析——循环依赖的解决方案

    一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...

  7. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

  8. Spring源码解析之ConfigurationClassPostProcessor(二)

    上一个章节,笔者向大家介绍了spring是如何来过滤配置类的,下面我们来看看在过滤出配置类后,spring是如何来解析配置类的.首先过滤出来的配置类会存放在configCandidates列表, 在代 ...

  9. Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

    Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...

随机推荐

  1. Linux 内核源码外编译 linux模块--编译驱动模块的基本方法

    1.先编写一个简单的hello模块,hello.c 源码如下: #ifndef __KERNEL__ # define __KERNEL__ #endif #ifndef MODULE # defin ...

  2. ObjectOutputStream和ObjectInputStream的简单使用

    使用ObjectOutputStream往文本写内容时,首先在文本里面标记开始,然后是内容,最后加上结束标示.如果想再次往文本里面添加内容的话,就要加在开始标示之后和结束标示之前,不然会读取不到写入的 ...

  3. unknow table alarmtemp error when drop database (mysql)

    Q: unknow table alarmtemp error when  drop database (mysql) D: alarmtemp is table in rtmd database. ...

  4. 矩阵儿快速幂 - POJ 3233 矩阵力量系列

    不要管上面的标题的bug 那是幂的意思,不是力量... POJ 3233 Matrix Power Series 描述 Given a n × n matrix A and a positive in ...

  5. Java中为什么字段不能被重写

    官方说法: 在一个类中,一个具有相同名称的字段隐藏了父类的父类的领域,即使他们的类型是不同的.在子类中,父类中的字段是不能用简单的名称引用.相反,该字段必须通过超级访问.一般来说,我们不建议隐藏字段, ...

  6. 用python批量下载贴吧图片 附源代码

    环境:windows 7 64位:python2.7:IDE pycharm2016.1 功能: 批量下载百度贴吧某吧某页的所有帖子中的所有图片 使用方法: 1.安装python2.7,安装re模块, ...

  7. Leetcode 516.最长回文子序列

    最长回文子序列 给定一个字符串s,找到其中最长的回文子序列.可以假设s的最大长度为1000. 示例 1:输入: "bbbab" 输出: 4 一个可能的最长回文子序列为 " ...

  8. poj2002 hash+邻接表优化Squares

    Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 17487   Accepted: 6643 Descript ...

  9. 【bzoj2083】[Poi2010]Intelligence test STL-vector+二分查找

    题目描述 霸中智力测试机构的一项工作就是按照一定的规则删除一个序列的数字,得到一个确定的数列.Lyx很渴望成为霸中智力测试机构的主管,但是他在这个工作上做的并不好,俗话说熟能生巧,他打算做很多练习,所 ...

  10. 一个 Observation

    $n$ 个小球分布在一个圆上,小球的颜色或黑或白.顺时针(或逆时针)遍历这 $n$ 个小球,记录下相邻两小球的颜色,得到 $n$ 个有序颜色对.我们有,(黑,白)和(白,黑)的数目一定相等(可能都是 ...