一、什么是簡單工廠模式
設計模式的核心是“分工”,通過分工將對象與職責划分的更細化,進而提升系統設計的可擴展性,使其更容易維護。
開閉原則:對擴展開放,對修改關閉;要增加一個新的處理邏輯,可以開一個新的類,不要在老的上面修改
依賴倒轉原則:依賴關系從具體轉向抽象,也就是說: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/