1. 程式人生 > >【Spring原始碼解析】—— 簡單工廠模式的BeanFactory的超簡版實現

【Spring原始碼解析】—— 簡單工廠模式的BeanFactory的超簡版實現

 一、什麼是簡單工廠模式

設計模式的核心是“分工”,通過分工將物件與職責劃分的更細化,進而提升系統設計的可擴充套件性,使其更容易維護。

 

開閉原則:對擴充套件開放,對修改關閉;要增加一個新的處理邏輯,可以開一個新的類,不要在老的上面修改

依賴倒轉原則:依賴關係從具體轉向抽象,也就是說: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/52776