1. 程式人生 > >Spring 實現兩種設計模式:工廠模式和單態模式

Spring 實現兩種設計模式:工廠模式和單態模式

本文摘自:李剛 著 《輕量級 Java EE企業應用實戰 Struts2+Spring+hibernate整合開發》

        在Spring 中大量使用的以下兩種設計模式:工廠模式單態模式

工廠模式可將Java 物件的呼叫者從被呼叫者的實現邏輯中分離出來,呼叫者只需關心被呼叫者必須滿足的規則(介面) ,而不必關心例項的具體實現過程。這是面向介面程式設計的優勢,能提高程式的解耦,避免所有的類以硬編碼方式耦合在一起。

        如果所有的類直接耦合,極易形成"骨牌效應",假如B 類呼叫了A 類,一旦A 類需要修改,則B 類也需要修改;假如C 類呼叫了B 類,則C 類也需要修改......依次類推,從而導致整個系統都需要改寫。造成"牽一髮而動全身",而系統重構的代價是相當高的。

        Spring 倡導”面向介面程式設計“,可以避免上述的問題,使設計良好的架構可保證系統重構的工作被封閉在重構的層內,絕不會影響其他層。

        Spring 容器是例項化和管理全部bean 的工廠,Spring 預設將所有的bean 設定成單態模式,無須自己完成單態模式,即對所有相同id 的bean 請求都將返回同一個共享例項。因此,單態模式可大大降低Java 物件在建立和銷燬時的系統開銷。

一. 單態模式的回顧

        單態模式限制了類例項的建立,但採用這種模式設計的類,可以保證僅有一個例項,並可提供訪問該例項的全域性訪問點。J2EE應用的大量元件,都需要保證一個類只有一個例項。

比如資料庫引擎訪問點只能有一個。

        更多的時候,為了提高效能,程式應儘量減少Java 物件的建立和銷燬時的開銷。使用單態模式可避免Java 類被多次例項化,讓相同類的全部例項共享同一記憶體區。

        為了防止單態模式的類被多次例項化,應將類的構造器設成私有,這樣就保證了只能通過靜態方法獲得類例項。而該靜態方法則保證每次返回的例項都是同一個,這就需將該類的例項設定成類屬性,由於該屬性需要被靜態方法訪問,因此該屬性應設成靜態屬性。

下面給出單態模式的示例程式碼:

package ppp;
//單態模式測試類
public class SingletonTest {
	//該類的一個普通屬性
	int value;
	//使用靜態屬性儲存該類的一個例項
	private static SingletonTest instance;
	//構造器私有化,避免該類被多次例項化
	private SingletonTest(){
		System.out.println("正在執行構造器...");
	}
	//提供靜態方法返回該類例項 
	public static SingletonTest getInstance(){
		//例項化類例項前,先檢查該例項是否存在
		if(instance == null){
			//如果不存在,則新建一個例項
			instance = new SingletonTest();
		}
		//返回該類的成員變數:該類的例項 
		return instance;	
	}
	//以下提供對普通屬性value的getter和setter方法
    public int getValue(){
    	return value;
    }

    public void setValue(int values){
    	this.value = values;	
    }
    public static void main(String args[]){
    	SingletonTest t1 = SingletonTest.getInstance();
    	SingletonTest t2 = SingletonTest.getInstance();
    	t2.setValue(9);
    	System.out.println(t1 == t2);
    }
}

        從程式最後的列印結果可以看出,該類的兩個例項完全相同。這證明單態模式類的全部例項是同一共享例項。程式裡雖然獲得了類的兩個例項,但實際上只執行一次構造器,因為對於單態模式的類,無論有多少次的建立例項請求,都只執行一次構造器。

二. 工廠模式的回顧

        工廠模式是根據呼叫資料返回某個類的一個例項,此類可以是多個類的某一個類。通常,這些類滿足共同的規則(介面)或父類。呼叫者只關心工廠生產的例項是否滿足某種規範,即實現的某個介面是否可供自己正常呼叫(呼叫者僅僅使用)。該模式給物件之間作出了清晰的角色劃分,降低程式的耦合。

        介面產生的全部例項通常用於實現相同介面,接口裡定義了全部例項共同擁有的方法,這些方法在不同的實現類中實現的方式不同。從而使程式呼叫者無須關心方法的具體實現,降低了系統異構的代價。

下面是工廠模式的示例程式碼:

package ppp;

//Person介面定義
public interface Person {
	public String sayHello(String name);
	public String sayGoodbye(String name);
}

該介面定義了Person規範,規範要求實現該介面的類必須具有以下兩個的方法:能打招呼,能告別。

package ppp;
//American類實現Person介面
public class American implements Person {
	public String sayHello(String name){
		return name+",hello";
	}
	public String sayGoodbye(String name)
	{
		return name+",goodbye";
	}
}

下面是Person類的另一個實現類:Chinese

package ppp;  
//Chinese類實現Person介面
public class Chinese implements Person {
	public String sayHello(String name){
		return name+",您好";
	}
	public String sayGoodbye(String name)
	{
		return name+",下次再見";
	}
}

然後再看Person工廠的程式碼:

package ppp;

public class PersonFactory {
	public Person getPerson(String ethnic)
	{
		if(ethnic.equalsIgnoreCase("chin"))
		{
			return new Chinese();
		}else{
			return new American();		
		}
	}
}

以上是最簡單的工廠模式框架,其主程式如下:

package ppp;

public class FactoryTest {
	public static void main(String[] args){
		//建立PersonFactory例項 ,獲得工廠例項 
		PersonFactory pf = new PersonFactory();
		//定義介面Person例項,面向介面程式設計 
		Person p = null;
		//使用工廠獲得person例項
	    p = pf.getPerson("chin");
	    //下面呼叫Person介面方法
	    System.out.println(p.sayHello("wawa"));
	    System.out.println(p.sayGoodbye("wawa"));
	    //使用工廠獲得Person的另一個例項
	    p = pf.getPerson("ame");
	    //再次呼叫Person介面的方法
	    System.out.println(p.sayHello("wawa"));
	    System.out.println(p.sayGoodbye("wawa"));
	}
}

由此可看出,主程式從Person 介面的具體類中解耦出來,而且程式呼叫者無須關心Person 的例項化過程,主程式僅僅與工廠服務定位結合在一起,可獲得所有工廠能產生的例項。具體類的變化,介面無須發生任何改變,呼叫者程式程式碼部分也無須發生任何改動。
下面是Spring 對這兩種模式的實現。

三. Spring 對單態與工廠模式的實現

        隨著Spring 提供工廠模式的實現,在使用Spring 時,無須自己提供工廠類。因為Spring容器是最大的工廠,而且是個功能超強的工廠。Spring 使用配置檔案管理所有的bean ,其配置檔案中bean 由Spring 工廠負責生成和管理。

下面是關於兩個例項的配置檔案:

<!--下面是xml檔案的檔案頭-->
<?xml version = "1.0" encoding = "gb2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
   "http://www.springsource.org/dtd/spring-beans.dtd">
<!--beans是Spring配置檔案的根元素-->
<beans>
<!--定義第一個bean,該bean的id是chinese-->
<bean id = "chinese" class = "ppp.Chinese"/>
<!--定義第二個bean,該bean的id是American-->
<bean id = "american" class = "ppp.American"/>
</beans>

主程式部分如下:

package ppp;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class SpringTest {
	public static void main(String[] args) {
		//例項化Spring容器
		ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
		//定義Person介面例項
		Person p = null;
		//通過Spring上下文獲得Chinese例項
		p = (Person)ctx.getBean("chinese");
		//執行chinese例項的方法
		System.out.println(p.sayHello("wawa"));
		System.out.println(p.sayGoodbye("wawa"));
		
		p = (Person)ctx.getBean("american");
		System.out.println(p.sayHello("wawa"));
		System.out.println(p.sayGoodbye("wawa"));
	}
}

       使用Spring 時,即使沒有工廠類PersonFactory ,程式一樣可以使用工廠模式, Spring完全可以提供所有工廠模式的功能。

       下面對主程式部分進行簡單的修改:   

package ppp;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class SpringTest{
	 public static void main(String[] args){
		 //例項化Spring容器
		 ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
		 //定義p1介面的例項p1
		 Person p1 = null;
		 //通過Spring上下文獲得Chinese例項
		 p1 = (Person)ctx.getBean("Chinese");
		 //定義p2介面的例項p2
		 Person p2 = null;
		 p2 = (Person)ctx.getBean("Chinese");
		 System.out.println(p1 == p2);
	 }
}

          程式的執行結果是:true

        表明Spring對接受容器管理的全部的bean,預設採用單態模式管理,建議不要隨意更改bean的行為方式。因為從效能上講,單態的bean比非單態的bean效能更為優秀。

        仔細檢查上面的程式碼就會發現如下的特點;

        (1)除測試部分的主程式外,程式碼並未出現Spring的特定類和介面。

        (2)呼叫者的程式碼,也就是測試用的主程式部分,僅僅面向Person的介面程式設計,而無需知道實現類的具體名稱。同時,通過修改配置檔案來徹底切換底層的具體實現類。

        (3)由於廠無需多個例項,因此工廠應該採用單態模式設計,其中Spring上下文也就是Spring工廠,已被設計成單態。

          Spring工廠模式,不僅提供了建立bean的功能,還提供了對bean的生命週期的管理。最重要的是還以管理bean和bean之間的依賴關係。

相關推薦

Spring 實現設計模式工廠模式模式

本文摘自:李剛 著 《輕量級 Java EE企業應用實戰 Struts2+Spring+hibernate整合開發》         在Spring 中大量使用的以下兩種設計模式:工廠模式和單態模式。 工廠模式可將Java 物件的呼叫者從被呼叫者的實現邏輯中分離出來,呼

Spring實現設計模式工廠模式模式

工廠模式可將Java 物件的呼叫者從被呼叫者的實現邏輯中分離出來,呼叫者只需關心被呼叫者必須滿足的規則(介面) ,而不必關心例項的具體實現過程。這是面向介面程式設計的優勢,能提高程式的解耦,避免所有的類以硬編碼方式耦合在一起。         如果所有的類直接耦合,極易形成

深入研究Spring-IoC:設計實現

一.Sprng IOC 解除了物件例項化造成的耦合現象;將物件的建立和對生命週期的管理交給了容器來管理,可以通過注入的方式將IOC容器中的物件供給開發者使用,極大方便了開發。 二.IOC容器系列的兩種設計和實現–BeanFactory和ApplicationCont

Spring代理方式JDK動態代理CGLIB動態代理

轉自 :https://blog.csdn.net/cckevincyh/article/details/54962920   代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可譯為”代理“,所謂代理,就是一個人或者一個機構代表另一個人或者另一個機構採取行動。

scala 基礎十二 scala apply的使用,工廠方法模式實現

定義 其他 返回 pack 新的 true 伴生對象 args null 1. apply 可以用來實現類似於靜態的初始化類的實例,請看下面實例 package smart.iot class applyclass { } class A {

處理瀏覽器端長時間執行JavaScript指令碼的優化方式定時器worker

第一種:定時器方式,把長時間的任務進行分割成一個數組,間隔一定的時間執行。 function timeProcessArray(items, process, callBack) { let todo = items.concat() setTimeout(function () {

執行緒的建立方式Thread類Runnable介面,它們都要複寫run方法

/*執行緒: * 1.如何在自定義的程式碼中,自定義一個執行緒呢? * * 通過對API的查詢,java已提供了對執行緒這類事物的描述。就是Thread類 * * 建立執行緒的第一種方式:繼承Thread類。 * 步驟: * 1.定義類繼承Thread。

Spring—AOP代理機制對比(JDKCGLib動態代理)

Sprign 動態代理機制 Spirng的AOP的動態代理實現機制有兩種,分別是: 1)JDK動態代理: 具體實現原理: 1、通過實現InvocationHandlet介面建立自己的呼叫處理器 2、

C++工廠模式的結合使用

單例模式: 簡單來說一個類只有一個例項且封裝性好。這裡用巨集定義實現。 animal_singleton.h #pragma once #include <iostream> #define IMPLEMENTION_SINGLETON_CL

Spring(十三)使用工廠方法來配置Bean的方式(靜態工廠方法&實例工廠方法)

color 示例 簡單的 rgs icc tostring pac ng- clas 通過調用靜態工廠方法創建Bean 1)調用靜態工廠方法創建Bean是將對象創建的過程封裝到靜態方法中。當客戶端需要對象時,只需要簡單地調用靜態方法,而不需要關心創建對象的具體細節。 2

設計模式(例 簡單工廠)

一.設計模式 1.什麼是設計模式 2.為什麼用設計模式 3.什麼時候使用設計模式 4.怎樣用設計模式 二.單例模式 1.單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。 通

Spring中常用的設計模式工廠模式

文章目錄 工廠模式 例項 1. 先實現簡單工廠 2. 工廠類(修改) 3. 增加配置檔案 4. 測試類 5. 總結 工廠模式 Beanfactory是一

C++ 設計模式模式觀察者監聽者模式

一、C++中有23種設計模式,大致分為建立型模式,結構型模式以及行為模式, 在這裡自己實現一下單例模式以及觀察者和監聽者模式 二、單例模式 我們通過維護一個static的成員變數來記錄唯一的物件例項,通過提供一個static的介面instance來獲得唯一的例項,就是一

Mysql讀寫分離的方法對比Spring+JPA應用層實現 vs Amoeba中介軟體實現

前段時間看了篇文章,講Youku網資料庫架構的演變,如何從最開始的讀寫分離,再到垂直分割槽,最後到水平分片,一步一步慢慢成熟的。看完之後很有衝動抽出一個模型來把這幾種技術都實現一下。      說幹就幹,首先是讀寫分離了,我使用的資料庫是Mysql,主從資料複製用的是半

我的設計模式工廠模式橋梁模式

工廠模式 橋梁模式 抽象工廠模式 1.簡單工廠模式 Factory Method Pattern能生產某類(接口管理)東東,可以指定特定的類延遲初始化: 使用全局變量Map減少類的初始化過程獲取接口下的全部實現類:ClassUtils2.抽象工廠模式 Abstract Factory

C#學習之設計模式工廠模式

缺陷 進行 type 系列 concrete 改變 cnblogs static 優劣   最近研究一下設計模式中工廠模式的應用,在此記錄如下:   什麽是工廠模式?   工廠模式屬於設計模式中的創造型設計模式的一種。它的主要作用是協助我們創建對象,為創建對象提供最佳的方式

設計模式工廠方法

card http tro 默認 方法 enter pre 繼承 bstr 設計模式:工廠方法 一、前言 前面我們說過模板方法被用在了工廠方法裏面,為什麽呢?工廠是制造產品的,需要按照一定的流程去創造產品,因此這一定的流程創造產品就是我們的模板了。工廠方法可以說用的很多

設計模式工廠方法模式

left 實例 設計模式 設計 通過 耦合度 creat margin 增加 一、簡單工廠模式 1、內容 不直接向客戶端暴露對象創建的實現細節,而是通過一個工廠類來負責創建產品類的實例 2、角色 1、工廠角色(Factory) 2、抽象產品角色(Product) 3、具體產

Java設計模式(一)之建立型模式工廠模式(簡單工廠模式+工廠方法模式

在面向物件程式設計中, 最通常的方法是一個new操作符產生一個物件例項,new操作符就是用來構造物件例項的。但是在一些情況下, new操作符直接生成物件會帶來一些問題。舉例來說,許多型別物件的建立需要一系列的步驟:你可能需要計算或取得物件的初始位置;選擇生成哪個子物件例項;或在你生成你需要的物件

Spring 通過工廠方法來配置bean

在Spring框架中建立Bean例項的時候中, 我們通常會利用配置檔案,也就是XML檔案形式 或者 annotation註解方式來配置bean. 在第一種利用配置檔案方式中, 還包括如下三小類 1、反射模式 2、工廠方法模式(本文重點) 3、Factory Be