設計模式單例模式
A. 請教 Java設計模式中的單例模式的懶漢式和餓漢式名字的由來,為什麼叫懶漢式 餓漢式
餓漢式是由抄the singleton instance is early created at complie time中的early音譯過來的,
懶漢式是由the singleton instance is lazily created at runtime中的lazily意譯過來的
B. 在Java中,單例設計模式是什麼意思有什麼優勢
單例模式:保證一個類在使用過程中,只有一個實例。優勢就是他的作用,這個類永回遠只有一答個實例。
步驟: 1. 將該類的構造方式私有;
2. 在內部實例化一個該類的實例;
3. 提供介面給外部訪問。
public class SingletonDemo {
private SingletonDemo (){}; // 1.
private static SingletonDemo mInstance = new SingletonDemo(); // 2.
public static SingletonDemo getInstance(){ // 3.
return mInstance;
}
}
C. 將一個類設計成單例設計模式,需要哪些步驟
單例模式(Singleton Pattern)是一個比較簡單的模式。
定義:
確保某一個類只有一個實例,而且自動實例化並向整個系統提供這個實例。
通用類圖:
通用代碼:
Singleton類稱為單例類,通過使用private的構造函數確保了在一個應用中只產生一個實例,並且是自行實例化的。
/**
* 線程安全的單例模式
* 餓漢式單例
* @author Administrator
*
*/
public class Singleton {
private static final Singleton singleton = new Singleton();
// 限制產生多個對象
private Singleton() {
}
// 通過該方法獲得實例對象
public static Singleton getSingleton() {
return singleton;
}
// 類中其他方法盡量是static
public static void doSomething() {
}
}
單例模式的優點:
由於單例模式在內存中只有一個實例,減少了內存開支,特別是一個對象需要頻繁地創建、銷毀時,而且創建或銷毀時性能又無法優化,單例模式的優勢就非常明顯了。
由於單例模式只生成一個實例,所以減少了系統的性能開銷,當一個對象的產生需要比較多的資源時,如讀取配置、產生其他依賴對象時,則可以通過在應用啟動時直接產生一個單例對象,然後用永久駐留內存的方式來解決。
單例模式可以避免對資源的多重佔用,例如一個寫文件動作,由於只有一個實例存在內存中,避免對同一個資源文件的同時寫操作。
單例模式可以在系統設置全局的訪問點,優化和共享資源訪問,例如可以設計一個單例類,負責所有數據表的映射處理。
單例模式的缺點:
單例模式一般沒有介面,擴展很困難,若要擴展,除了修改代碼基本上沒有第二種途徑可以實現。
單例模式對測試是不利的。在並行開發環境中,如果單例模式沒有完成,是不能進行測試的,沒有介面也不能用mock的方式虛擬一個對象。
單例模式與單一職責原則有沖突。一個類應該只實現一個邏輯,而不關心它是否是單例的,是不是要單例取決於環境,單例模式把「要單例」和業務邏輯融合在一個類中。
單例模式的使用場景:
要求生成唯一序列號的環境;
在整個項目中需要一個共享訪問點或共享數據,例如一個Web頁面上的計數器,可以不用把每次刷新都記錄到資料庫中,使用單例模式保持計數器的值,並確保是線程安全的;
創建一個對象需要消耗的資源過多,如要訪問IO和資料庫等資源;
需要定義大量的靜態常量和靜態方法(如工具類)的環境,可以採用單例模式(當然,也可以直接聲明為static的方式)。
單例模式的注意事項:
1. 在高並發情況下,請注意單例模式的線程同步問題。
/**
* 懶漢式單例
* @author Administrator
*
*/
public class Singleton2 {
private static Singleton2 singleton = null;
// 限制產生多個對象
private Singleton2() {
}
// 通過該方法獲得實例對象
public static Singleton2 getSingleton() {
synchronized (singleton) {
if (singleton == null) {
singleton = new Singleton2();
}
}
return singleton;
}
}
如果不加synchronized進行控制,如果第一個線程A執行到singleton = new Singleton2(),但還沒有獲得對象,第二個線程B也在執行,執行到if (singleton == null)判斷,那麼線程B獲得判斷條件為真,於是繼續運行下去,線程A和B都獲得了對象,內存中就出現了兩個對象。
建議使用餓漢式單例,那是線程安全的單例模式。
2. 需要考慮對象的復制情況。在Java中,若實現Cloneable介面,並實現了clone方法,則可以直接通過對象復制方式創建一個新對象,對象復制是不用調用類的構造函數的。
3. 注意JVM的垃圾回收機制,如果我們的一個單例對象在內存中長久不使用,JVM就認為這是一個垃圾對象,在CPU資源空閑的情況下該對象會被清理掉,下次再調用時就需要產生一個新對象。如果該對象作為有狀態值的管理,則會出現狀態恢復原狀的情況,就會出現故障。
有兩種方法可以解決該問題
1、由容器管理單例的生命周期
Java EE容器或者框架級容器(如Spring)可以讓對象長久駐留內存。
2、狀態隨時記錄
可以使用非同步記錄的方式,或者使用觀察者模式,記錄狀態的變化,寫入文件或寫入資料庫中,確保即使單例對象重新初始化也可以從資源環境獲得銷毀前的數據,避免應用數據丟失。
單例模式的擴展:
能產生固定數量實例的單例模式
/**
* 能產生固定數量實例的單例模式
* @author Administrator
*
*/
public class Singleton3 {
// 最多能產生的實例數
private static int maxNumOfSingleton = 2;
// 定義一個列表,容納所有實例
private static ArrayList<Singleton3> singletonList = new ArrayList<Singleton3>();
// 產生所有對象
static {
for (int i = 0; i < maxNumOfSingleton; i++) {
singletonList.add(new Singleton3());
}
}
// 限制其他類生成對象
private Singleton3() {
}
// 隨機獲得一個實例
public static Singleton3 getInstance() {
Random random = new Random();
return singletonList.get(random.nextInt(maxNumOfSingleton));
}
}
D. java 單例模式(單一設計模式)怎麼保證的只能生成一個實例求更具體的解釋
我覺得這個注釋已經說得很清楚了,GOF的23種設計模式說得很清楚,單例,就是一版個權Class在一個Classloader中只有一個實例。在類中寫一個私有的構造器,那麼除了自己,在其他類中都無法創建這個類的實例,其中有一個靜態域也就是自己的實例,由自己NEW出來的,其中的可以被其他類訪問的靜態方法只是返回這個實例,而不會去再New,所以保證了不能再創建第二個!
E. 單件模式的設計模式-單件模式(singleton)
我們分兩種方式來討論一個單件類的創建,一是將一個類的公共構造函數改為私有,另一種方式是保留類的公共構造函數,通過一個靜態成員來決定是否要返回一個類實例。
Singleton模式
Singleton可以說是《Design Pattern》中最簡單也最實用的一個設計模式。那麼,什麼是Singleton?
顧名思義,Singleton就是確保一個類只有唯一的一個實例。Singleton主要用於對象的創建,這意味著,如果某個類採用了Singleton模式,則在這個類被創建後,它將有且僅有一個實例可供訪問。很多時候我們都會需要Singleton模式,最常見的比如我們希望整個應用程序中只有一個連接資料庫的Connection實例;又比如要求一個應用程序中只存在某個用戶數據結構的唯一實例。我們都可以通過應用Singleton模式達到目的。
一眼看去,Singleton似乎有些像全局對象。但是實際上,並不能用全局對象代替Singleton模式,這是因為:其一,大量使用全局對象會使得程序質量降低,而且有些編程語言例如C#,根本就不支持全局變數。其二,全局對象的方法並不能阻止人們將一個類實例化多次:除了類的全局實例外,開發人員仍然可以通過類的構造函數創建類的多個局部實例。而Singleton模式則通過從根本上控制類的創建,將保證只有一個實例這個任務交給了類本身,開發人員不可能再有其它途徑得到類的多個實例。這一點是全局對象方法與Singleton模式的根本區別。
F. 你熟悉的設計模式有哪些寫出單例模式的實現代碼
23個設計模式:
根據目的設計模式可以分為創造模式,結構模式和行為模式,創建模式用於處理對象的創建。結構模式用於處理類或對象的組合。
行為模式用於描述類或對象如何交互以及如何分配職責,創建模式用於處理對象的創建。主要包括以下五種設計模式:
工廠方法模式()
抽象工廠模式(AbstractFactoryPattern)
建造者模式(BuilderPattern)
原型模式(PrototypePattern)
單例模式(SingletonPattern)
結構模式用於處理類或對象的組合,包括以下七個設計模式:
適配器模式(AdapterPattern)
橋接模式(BridgePattern)
組合模式(CompositePattern)
裝飾者模式(DecoratorPattern)
外觀模式(FacadePattern)
享元模式(FlyweightPattern)
代理模式(ProxyPattern)
行為模式描述類或對象如何交互以及它們如何分配職責。它由以下11種設計模式組成:
責任鏈模式(Chain的ResponsibilityPattern)
命令模式(CommandPattern)
解釋器模式(InterpreterPattern)
迭代器模式(IteratorPattern)
中介者模式(MediatorPattern)
備忘錄模式(MementoPattern)
觀察者模式(ObserverPattern)
狀態模式(StatePattern)
策略模式(StrategyPattern)
模板方法模式(TemplateMethodPattern)
訪問者模式(VisitorPattern)
單例模式實現1:
公共類Singleton{
類共享實例對象
私有靜態單例;單例=零;
//私有構造函數
私有Singleton(){
系統。出去了。這是單例!!);
}
//獲取單例方法
公共同步靜態單例getInstance(){
//確定共享對象是否為空,如何空一個新對象
If(singleton==null){
singleton=newsingleton();
}
返回單例。
}
}
單例模式實現2:
公共類Singleton{
類共享實例對象實例化
=newSingleton();
//私有構造函數
私有Singleton(){
系統:出去了,這是單例!!);
}
//獲取單例方法
公共靜態單例getInstance(){
直接返回共享對象
返回單例。
}
}
(6)設計模式單例模式擴展閱讀:
注意事項:
設計模式主要分三個類型:創建型和行為型。
Singleton:確保一個類只有一個實例,並為其提供一個全局訪問點
AbstractFactory:提供一個介面,用於創建一系列相關或相互依賴的對象,而無需指定它們的具體類。
FactoryMethod:定義一個用於創建對象的介面,並讓子類決定實例化哪個類。工廠方法將類的實例化延遲到子類。
Builder:將復雜對象的構造與其表示分離,使相同的構造過程可以創建不同的表示。
Prototype:指定要使用Prototype實例創建的對象的類型,並復制該原型來創建一個新對象。
Composite:將對象組合成樹狀結構,以表示整體各部分之間的關系。組合使用戶一致地使用單個對象和組合對象。
Facade:為子系統fa中的一組介面提供一致的介面。Ade提供了一個高級介面,使子系統更易於使用。
Proxy:為其他對象提供一個代理,以控制對該對象的訪問
Adapter:將一個介面類轉換為客戶想要的另一個介面類。適配器模式使那些由於介面不兼容而無法一起工作的類一起工作。
Decrator:式比子類化更靈活,可以為對象動態添加一些額外的職責。
Bridge:模式將抽象部分與其實現部分分離,以便它們可以獨立地更改。
Flyweight:享元模式
G. java中幾種設計模式(單例模式,適配器模式
1、單例模式:也分餓漢式單例模式(創建對象)與懶漢式單例模式(未創建對象)
代碼實現:
餓漢式單例模式:
懶漢式單例模式:
2、適配器模式:
介面:
實現介面的類:
H. spring主要運用那些設計模式單例模式是怎麼實現的
1.spring主要運抄用那些設計模式:
單例,工廠
2.單例模式實現:
核心是私有構造子
通過該類的靜態方法 獲取唯一的對象
其中主要是2種:
a.餓漢式
class Singleton {
private static Singleton instance=new Singleton();
private Singleton(){}
static Singleton getInstance() {
return instance;
}
}
b.懶漢式
class Singleton {
private static Singleton instance=null;
private Singleton(){}
static Singleton getInstance() {
if(instance==null)
instance=new Singleton();
return instance;
}
}
I. spring主要運用那些設計模式,單例模式是怎麼實現的
設計模式作為工作學習中的枕邊書,卻時常處於勤說不用的尷尬境地,也不是我們時常忘記,只是一直沒有記憶。
今天,螃蟹在IT學習者網站就設計模式的內在價值做一番探討,並以spring為例進行講解,只有領略了其設計的思想理念,才能在工作學習中運用到「無形」。
Spring作為業界的經典框架,無論是在架構設計方面,還是在代碼編寫方面,都堪稱行內典範。好了,話不多說,開始今天的內容。
spring中常用的設計模式達到九種,我們舉例說明:
第一種:簡單工廠
又叫做靜態工廠方法(StaticFactory Method)模式,但不屬於23種GOF設計模式之一。
簡單工廠模式的實質是由一個工廠類根據傳入的參數,動態決定應該創建哪一個產品類。
spring中的BeanFactory就是簡單工廠模式的體現,根據傳入一個唯一的標識來獲得bean對象,但是否是在傳入參數後創建還是傳入參數前創建這個要根據具體情況來定。如下配置,就是在 HelloItxxz 類中創建一個 itxxzBean。
<beans>
<bean id="singletonBean" class="com.itxxz.HelloItxxz">
<constructor-arg>
<value>Hello! 這是singletonBean!value>
</constructor-arg>
</ bean>
<bean id="itxxzBean" class="com.itxxz.HelloItxxz"
singleton="false">
<constructor-arg>
<value>Hello! 這是itxxzBean! value>
</constructor-arg>
</bean>
</beans>
第二種:工廠方法(Factory Method)
通常由應用程序直接使用new創建新的對象,為了將對象的創建和使用相分離,採用工廠模式,即應用程序將對象的創建及初始化職責交給工廠對象。
一般情況下,應用程序有自己的工廠對象來創建bean.如果將應用程序自己的工廠對象交給Spring管理,那麼Spring管理的就不是普通的bean,而是工廠Bean。
螃蟹就以工廠方法中的靜態方法為例講解一下:
import java.util.Random;
public class StaticFactoryBean {
public static Integer createRandom() {
return new Integer(new Random().nextInt());
}
}
建一個config.xm配置文件,將其納入Spring容器來管理,需要通過factory-method指定靜態方法名稱
<bean id="random"
class="example.chapter3.StaticFactoryBean" factory-method="createRandom" //createRandom方法必須是static的,才能找到 scope="prototype"
/>
測試:
public static void main(String[] args) {
//調用getBean()時,返回隨機數.如果沒有指定factory-method,會返回StaticFactoryBean的實例,即返回工廠Bean的實例 XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("config.xml")); System.out.println("我是IT學習者創建的實例:"+factory.getBean("random").toString());
}
第三種:單例模式(Singleton)
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
spring中的單例模式完成了後半句話,即提供了全局的訪問點BeanFactory。但沒有從構造器級別去控制單例,這是因為spring管理的是是任意的java對象。
核心提示點:Spring下默認的bean均為singleton,可以通過singleton=「true|false」 或者 scope=「?」來指定
第四種:適配器(Adapter)
在Spring的Aop中,使用的Advice(通知)來增強被代理類的功能。Spring實現這一AOP功能的原理就使用代理模式(1、JDK動態代理。2、CGLib位元組碼生成技術代理。)對類進行方法級別的切面增強,即,生成被代理類的代理類, 並在代理類的方法前,設置攔截器,通過執行攔截器重的內容增強了代理方法的功能,實現的面向切面編程。
Adapter類介面:Target
public interface AdvisorAdapter {
boolean supportsAdvice(Advice advice);
MethodInterceptor getInterceptor(Advisor advisor);
} MethodBeforeAdviceAdapter類,Adapter
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
第五種:包裝器(Decorator)
在我們的項目中遇到這樣一個問題:我們的項目需要連接多個資料庫,而且不同的客戶在每次訪問中根據需要會去訪問不同的資料庫。我們以往在spring和hibernate框架中總是配置一個數據源,因而sessionFactory的dataSource屬性總是指向這個數據源並且恆定不變,所有DAO在使用sessionFactory的時候都是通過這個數據源訪問資料庫。但是現在,由於項目的需要,我們的DAO在訪問sessionFactory的時候都不得不在多個數據源中不斷切換,問題就出現了:如何讓sessionFactory在執行數據持久化的時候,根據客戶的需求能夠動態切換不同的數據源?我們能不能在spring的框架下通過少量修改得到解決?是否有什麼設計模式可以利用呢?
首先想到在spring的applicationContext中配置所有的dataSource。這些dataSource可能是各種不同類型的,比如不同的資料庫:Oracle、SQL Server、MySQL等,也可能是不同的數據源:比如apache 提供的org.apache.commons.dbcp.BasicDataSource、spring提供的org.springframework.jndi.JndiObjectFactoryBean等。然後sessionFactory根據客戶的每次請求,將dataSource屬性設置成不同的數據源,以到達切換數據源的目的。
spring中用到的包裝器模式在類名上有兩種表現:一種是類名中含有Wrapper,另一種是類名中含有Decorator。基本上都是動態地給一個對象添加一些額外的職責。
第六種:代理(Proxy)
為其他對象提供一種代理以控制對這個對象的訪問。 從結構上來看和Decorator模式類似,但Proxy是控制,更像是一種對功能的限制,而Decorator是增加職責。
spring的Proxy模式在aop中有體現,比如JdkDynamicAopProxy和Cglib2AopProxy。
第七種:觀察者(Observer)
定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
spring中Observer模式常用的地方是listener的實現。如ApplicationListener。
第八種:策略(Strategy)
定義一系列的演算法,把它們一個個封裝起來,並且使它們可相互替換。本模式使得演算法可獨立於使用它的客戶而變化。
spring中在實例化對象的時候用到Strategy模式
在SimpleInstantiationStrategy中有如下代碼說明了策略模式的使用情況:
第九種:模板方法(Template Method)
定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。
Template Method模式一般是需要繼承的。這里想要探討另一種對Template Method的理解。spring中的JdbcTemplate,在用這個類時並不想去繼承這個類,因為這個類的方法太多,但是我們還是想用到JdbcTemplate已有的穩定的、公用的資料庫連接,那麼我們怎麼辦呢?我們可以把變化的東西抽出來作為一個參數傳入JdbcTemplate的方法中。但是變化的東西是一段代碼,而且這段代碼會用到JdbcTemplate中的變數。怎麼辦?那我們就用回調對象吧。在這個回調對象中定義一個操縱JdbcTemplate中變數的方法,我們去實現這個方法,就把變化的東西集中到這里了。然後我們再傳入這個回調對象到JdbcTemplate,從而完成了調用。這可能是Template Method不需要繼承的另一種實現方式吧。
J. 什麼是單例設計模式
java模式之單例模式:
單例模式確保一個類只有一個實例,自行提供這個實例並向整個系統提供這個實例。
特點:
1,一個類只能有一個實例
2,自己創建這個實例
3,整個系統都要使用這個實例
例: 在下面的對象圖中,有一個"單例對象",而"客戶甲"、"客戶乙" 和"客戶丙"是單例對象的三個客戶對象。可以看到,所有的客戶對象共享一個單例對象。而且從單例對象到自身的連接線可以看出,單例對象持有對自己的引用。
Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。在很多操作中,比如建立目錄 資料庫連接都需要這樣的單線程操作。一些資源管理器常常設計成單例模式。
外部資源:譬如每台計算機可以有若干個列印機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到列印機中。每台計算機可以有若干個通信埠,系統應當集中管理這些通信埠,以避免一個通信埠被兩個請求同時調用。內部資源,譬如,大多數的軟體都有一個(甚至多個)屬性文件存放系統配置。這樣的系統應當由一個對象來管理這些屬性文件。
一個例子:Windows 回收站。
在整個視窗系統中,回收站只能有一個實例,整個系統都使用這個惟一的實例,而且回收站自行提供自己的實例。因此,回收站是單例模式的應用。
兩種形式:
1,餓漢式單例類
public class Singleton {
private Singleton(){}
//在自己內部定義自己一個實例,是不是很奇怪?
//注意這是private 只供內部調用
private static Singleton instance = new Singleton();
//這里提供了一個供外部訪問本class的靜態方法,可以直接訪問
public static Singleton getInstance() {
return instance;
}
}
2,懶漢式單例類
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這個方法比上面有所改進,不用每次都進行生成對象,只是第一次
//使用時生成實例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
第二中形式是lazy initialization,也就是說第一次調用時初始Singleton,以後就不用再生成了。