<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    I want to fly higher
    programming Explorer
    posts - 114,comments - 263,trackbacks - 0
    -序言: 
        1.Java的正式發(fā)行名稱           工程版本號(hào)
          JDK 1.1.x / JRE 1.1.x           1.1
          Java2 Platform,Standard Edition,v 1.2     1.2
          Java2 Platform,Standard Edition,v 1.3     1.2
          Java2 Platform,Standard Edition,v 1.4     1.2
          Java2 Platform,Standard Edition,v 5.0     1.5
          Java Platform,Standard Edition,5       1.6
        2.術(shù)語:
             1.Java語言支持4種類型:
                  接口(interface) 類(class) 數(shù)組(array)  基本類型(primitive),前3中類型通常被稱為引用類型,類實(shí)例和數(shù)組是對(duì)象,而基本類型的值則不是對(duì)象。
             2.類的成員由其域(field),方法(method),成員類(member class)和成員接口(member interface)組成.
             3.方法的簽名(signature)由它的名稱和所有的參數(shù)類型組成,簽名不包括它的返回類型。
             4.繼承(inheritance),作為子類化(subclassing)的同義詞
             5.不再使用接口繼承這種說法,而是簡(jiǎn)單的說一個(gè)類實(shí)現(xiàn)(implement)了另一個(gè)接口或者說一個(gè)接口擴(kuò)展(extend)了另一個(gè)接口.
             6.描述沒有指定訪問級(jí)別的情況下所使用的訪問級(jí)別,使用了包級(jí)私有(package-private),而不是如JLS(Java Language Specifications),6.6.1所使用的技術(shù)性術(shù)語"缺省訪問(default access)"級(jí)別.
             7.導(dǎo)出的API(exported API)或者簡(jiǎn)單的說API,是指類,接口,構(gòu)造器,成員,和序列化形式,程序員可以通過他們可以訪問類,接口夠或者包。使用API編寫程序的程序員被稱為該API的用戶(user),在類的實(shí)現(xiàn)中使用了API的類被稱為該API的客戶(client).
             8.類,接口,構(gòu)造器,成員以及序列化的形式被統(tǒng)稱為API元素(API element),導(dǎo)出的API由所有可在該API的包之外訪問的API元素組成。任何客戶端都可以使用這些API元素,而API的創(chuàng)建者負(fù)責(zé)支持這些API元素。Javadoc工具類在默認(rèn)情況下也正是為這些元素生成文檔,這絕非偶然。不嚴(yán)格的講,一個(gè)類的導(dǎo)出的API是由每個(gè)公有(public)類或者接口中所有公有的或者受保護(hù)的(protected)成員和構(gòu)造器組成.

        第一條:考慮用靜態(tài)工廠方法代替構(gòu)造器
     
          1.對(duì)于類來說,為了讓客戶端獲取其自身的一個(gè)實(shí)例,最常用的辦法就是提供一個(gè)公有的構(gòu)造器。還有一種方法,也應(yīng)該在每個(gè)程序員的工具箱中占有一席之地。類可以提供一個(gè)公有的靜態(tài)工廠方法(static factory method),其時(shí)一個(gè)返回類實(shí)例的靜態(tài)方法。如:
       public static Boolean valueOf(boolean b)
       {
        return b ? Boolean.TRUE : Boolean.FALSE;
       }
          :靜態(tài)工廠方法與設(shè)計(jì)模式的工廠方法模式不同。本條目所指的靜態(tài)工廠方法并不直接對(duì)應(yīng)設(shè)計(jì)模式的工廠方法。 類可以通過靜態(tài)工廠方法提供他的客戶端,而不是通過提供構(gòu)造器
         2.優(yōu)勢(shì):
              1.靜態(tài)工廠方法與構(gòu)造器不同的第一大優(yōu)勢(shì)在于:他們有名稱。如果構(gòu)造器的參數(shù)本身沒有確切的描述正被返回的對(duì)象,那么具有適當(dāng)名稱的靜態(tài)工廠方法會(huì)更容易使用,產(chǎn)生的客戶端代碼也更易讀。
      如:BigInteger(int,int,Random),返回的可能是素?cái)?shù),如果用BigInteger.probablePrime的靜態(tài)工廠方法來表示,顯示更清楚。1.4的發(fā)行版本中最終增加了這個(gè)方法。
              2.一個(gè)類只能有一個(gè)帶有指定簽名的構(gòu)造器,編程人員通常避開這一限制是提供兩個(gè)構(gòu)造器,而它們的參數(shù)列表只是在參數(shù)列表順序上有所不同。實(shí)際上這不好。對(duì)于這樣的API,client永遠(yuǎn)也記不住該調(diào)用哪個(gè)構(gòu)造器,結(jié)果通常會(huì)調(diào)用錯(cuò)誤的構(gòu)造器。并且讀到這些構(gòu)造器的代碼時(shí),如果沒有參考文檔,也不知所云。所以由于靜態(tài)工廠方法有名稱,所以他們不受上述限制。當(dāng)一個(gè)類需要多個(gè)帶有相同簽名的構(gòu)造器(只是參數(shù)列表順序不同)時(shí),就用靜態(tài)工廠方法代替構(gòu)造器并且慎重選擇名稱已突出他們之間的區(qū)別。
              3.靜態(tài)工廠方法與構(gòu)造器不同的第二大優(yōu)勢(shì)在于,不必再每次調(diào)用它們的時(shí)候都創(chuàng)建一個(gè)新對(duì)象。
                   這使得不可變類可以使用預(yù)先構(gòu)建好的實(shí)例,或者將構(gòu)建好的實(shí)例緩存起來,進(jìn)行重復(fù)利用,從而避免創(chuàng)建不必要的重復(fù)對(duì)象。Boolean.valueOf(boolean)說明了這項(xiàng)技術(shù),它從來不創(chuàng)建對(duì)象。
       這類似于Flyweight模式。如果程序經(jīng)常請(qǐng)求創(chuàng)建相同的對(duì)象,并且創(chuàng)建對(duì)象的代價(jià)很高,則這項(xiàng)技術(shù)可以極大的提高性能。
       靜態(tài)工廠方法能夠?yàn)橹貜?fù)的調(diào)用返回相同對(duì)象,這有助于類總能嚴(yán)格控制在某個(gè)時(shí)刻那些實(shí)例應(yīng)該存在。這種類被稱為實(shí)例受控的類。instance-controlled.編寫實(shí)例受控的類有幾個(gè)原因:
                    1.使得類可以確保它是一個(gè)單例或者是不可實(shí)例化的
                    2.使得不可變的類確保不會(huì)存在兩個(gè)相等的實(shí)例,即當(dāng)且僅當(dāng)a == b的時(shí)候才有a.equals(b)為true.如果類保證了這一點(diǎn),其客戶端就可以利用==操作符來代替equals(Object)方法,這樣可以提高性能。枚舉類型保證了這一點(diǎn)。
              4.靜態(tài)工廠方法與構(gòu)造器不同的第三大優(yōu)勢(shì)在于,它們可以返回原返回類型的任何子類型對(duì)象:
                   這樣我們?cè)谶x擇返回對(duì)象的類時(shí)就有了更大的靈活性.
                   這種靈活性的一種應(yīng)用是,API可以返回對(duì)象,同時(shí)又不會(huì)使對(duì)象的類變成公有的,以這種方式因此實(shí)現(xiàn)類會(huì)使API變的非常簡(jiǎn)潔.該項(xiàng)技術(shù)適用于基于接口的框架,interface-based-framework.
       接口為靜態(tài)工廠方法提供了自然返回類型。因接口中不能有靜態(tài)方法,按照慣例,接口Type的靜態(tài)工廠方法被放在一個(gè)名為Types的不可實(shí)例化的類中。
               例子1:
                    Java Collections Framework的集合接口有32個(gè)便利實(shí)現(xiàn),分別提供了不可修改的集合,同步集合等。幾乎所有這些實(shí)現(xiàn)都通過靜態(tài)工廠方法在一個(gè)不可實(shí)例化的類java.utils.Collections中導(dǎo)出。所有返回對(duì)象都是非公有的。
        如:
          public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)
          {
                return new UnmodifiableCollection<>(c);
           }
            
           static class UnmodifiableCollection<E> implements Collection<E>, Serializable
           UnmodifiableCollection定義在Collections中,是非public。
               現(xiàn)在Collections Framework Api被導(dǎo)出32個(gè)獨(dú)立公有類的那種實(shí)現(xiàn)方式要小的多,每種便利實(shí)現(xiàn)都對(duì)應(yīng)一個(gè)類。這不僅僅是指API數(shù)量上的減少,也是概念意義上的減少,用戶知道被返回的對(duì)象是由相關(guān)的接口精確指定的,所以它們不需要閱讀相關(guān)的類文檔。使用這種靜態(tài)工廠方法時(shí),甚至要求客戶端通過接口來引用被返回的對(duì)象,而不是通過它的實(shí)現(xiàn)類來引用被返回的對(duì)象,這是一種良好的習(xí)慣。
           公有的靜態(tài)工廠方法所返回的對(duì)象的類不僅可以是非公有的,而且該類還可以隨著每次調(diào)用而發(fā)生變化,這取決于靜態(tài)工廠方法的參數(shù)值。只要是已生命的返回類型的子類型,都是允許的。
           為了維護(hù)軟件的可維護(hù)性和性能,返回的對(duì)象的類也可能隨著發(fā)行版本的不同而不同。
           如:java.util.EnumSet,沒有公用構(gòu)造器,只有靜態(tài)工廠方法。他們返回兩種實(shí)現(xiàn)類之一,具體取決于底層枚舉數(shù)組的大小;如果它的元素有64個(gè)或者更少,就像大多數(shù)枚舉類型一樣,靜態(tài)工廠方法返回一個(gè)RegularEnumSet實(shí)例,用單個(gè)long支持;如果枚舉類型有65個(gè)或者更多,工廠就返回JumboEnumSet實(shí)例,用long數(shù)組進(jìn)行支持。
           如:
            public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)
            {
                Enum[] universe = getUniverse(elementType);
                if (universe == null)
                    throw new ClassCastException(elementType + " not an enum");
        
                if (universe.length <= 64)
                    return new RegularEnumSet<>(elementType, universe);
                else
                    return new JumboEnumSet<>(elementType, universe);
            }
               這兩個(gè)實(shí)現(xiàn)類的存在對(duì)于客戶端來說是不可見的。如果RegularEnumSet不能再給小的枚舉類型提供性能優(yōu)勢(shì),就可能從未來的發(fā)行版本中將它刪除,不會(huì)造成不良的影響。同樣的了,如果證明對(duì)性能要好處,也可能在未來的發(fā)行版本中添加第三甚至第四個(gè)Enum實(shí)現(xiàn)。客戶端永遠(yuǎn)也不知道也不關(guān)心他們從工廠方法得到的對(duì)象的類,他們只關(guān)心他是EnumSet的某個(gè)子類即可。
           class RegularEnumSet<E extends Enum<E>> extends EnumSet<E>,非public.
           class JumboEnumSet<E extends Enum<E>> extends EnumSet<E>,非public.
               靜態(tài)工廠方法返回的對(duì)象所屬的類,在編寫包含該靜態(tài)工廠方法的類時(shí)可以不必存在。這種靈活的靜態(tài)工廠方法構(gòu)成了服務(wù)提供者框架,Service Provider Framework的基礎(chǔ)。如JDBC API。服務(wù)提供者框架是指這樣一個(gè)系統(tǒng),多個(gè)服務(wù)提供者實(shí)現(xiàn)一個(gè)服務(wù),系統(tǒng)為服務(wù)提供者的客戶端提供多個(gè)實(shí)現(xiàn),把它們從多個(gè)實(shí)現(xiàn)中解耦出來。
               服務(wù)器提供者框架中有三個(gè)重要的組件:服務(wù)接口(Service Interface),這是提供者實(shí)現(xiàn)的,提供者注冊(cè)API,provider registration API,這是系統(tǒng)用來注冊(cè)實(shí)現(xiàn),讓客戶端訪問它們的;服務(wù)訪問API,Service Access API,是客戶端用來獲取服務(wù)實(shí)例的。服務(wù)訪問API一般允許但是不要求客戶端指定某種選擇提供者的條件.如果沒有這樣的規(guī)定,API就會(huì)返回默認(rèn)實(shí)現(xiàn)的 一個(gè)實(shí)例。服務(wù)訪問API是靈活的靜態(tài)工廠,它構(gòu)成了服務(wù)提供者框架的基礎(chǔ).
           服務(wù)提供者框架的第四個(gè)組件是可選的:服務(wù)提供者接口,Service Provider Interface,這些提供者負(fù)責(zé)創(chuàng)建器服務(wù)實(shí)現(xiàn)的實(shí)例。如果沒有服務(wù)提供者接口,實(shí)現(xiàn)就按照類名來注冊(cè),并通過反射方式進(jìn)行實(shí)例化。對(duì)于JDBC來說,Connection就是它的服務(wù)接口,DriverManager.registerDriver就是提供者注冊(cè)API,DriverManager.getConnection是服務(wù)訪問API,Driver就是服務(wù)提供者接口。
           服務(wù)提供者框架模式有著無數(shù)種變體.,如服務(wù)訪問API可以利用適配器模式,返回被提供者需要的更豐富的服務(wù)接口:
         5.靜態(tài)工廠方法的第四大優(yōu)勢(shì)在于,在創(chuàng)建參數(shù)化類型實(shí)例的時(shí)候,他們使代碼變得更加簡(jiǎn)潔。
              如在使用參數(shù)化的類的構(gòu)造器時(shí),即時(shí)類型參數(shù)很明顯,也必須指明。如:通常要求你接連兩次提供類型參數(shù).
          Map<String,List<String>> m = new HashMap<String,List<String>>
          隨著類型參數(shù)越來越長(zhǎng),越來越復(fù)雜,這一冗長(zhǎng)的說明也很快變的痛苦起來。如果有靜態(tài)工廠方法,編譯器就可以替你找到類型參數(shù)。這被稱為類型推倒,type inference.如假設(shè)HashMap提供了這個(gè)工廠工廠:
          public static <K,V> HashMap<K,V> newInstance()
          {
           return new HashMap<K,V>();
          }
          你就可以簡(jiǎn)潔的代碼替換上面繁瑣的說明:
           Map<String,List<String>> m = HashMap.newInstance();
          目前1.6版本的標(biāo)準(zhǔn)集合還沒有提供工廠方法,但是可以把這些方法放在你自己的工具類中。更重要的是,可以把這樣的靜態(tài)工廠放在你自己的參數(shù)化的類中。
         6.靜態(tài)工廠方法的主要缺點(diǎn)在于,類如果不含公有或者受保護(hù)的構(gòu)造器,就不能被子類化。
              對(duì)于公有的靜態(tài)工廠所返回的非公有類,也同樣如此。如,你想講Collections Framework中的任何方便的實(shí)現(xiàn)類子類化,是不可能的。
              但是這樣有時(shí)候也有好處,即它鼓勵(lì)程序員使用復(fù)合compostion,而不是繼承。
         7.靜態(tài)工廠方法的第二個(gè)缺點(diǎn)在于,他們與其他的靜態(tài)方法實(shí)際上沒有任何區(qū)別。在API文檔中,他們沒有像構(gòu)造器那樣在API文檔中明確標(biāo)識(shí)出來,因此對(duì)于提供了靜態(tài)工廠方法而不是構(gòu)造器的類來說,要想查明如何實(shí)例化一個(gè)類,這是非常困難的。javadoc工具總有一天會(huì)注意到靜態(tài)工廠方法。同時(shí),你通過在類或者接口注釋中關(guān)注靜態(tài)工廠,并遵守標(biāo)準(zhǔn)的命名習(xí)慣,也可以彌補(bǔ)這一劣勢(shì)。下面是靜態(tài)工廠的一些慣用名稱:
              1.valueOf-不太嚴(yán)格講,該方法返回的實(shí)例與它的參數(shù)具有相同的值。這樣的靜態(tài)工廠方法實(shí)際上是類型轉(zhuǎn)換方法。
              2.of-valueOf的一種更為簡(jiǎn)潔的替代,在EnumSet中使用并流行起來。
              3.getInstance,返回的實(shí)例是通過方法的參數(shù)來描述的。但是不能夠說與參數(shù)具有同樣的值。對(duì)于單例Singleton來說,該方法沒有參數(shù),并返回唯一的實(shí)例。
              4.newInstance,向getInstance一樣,但newInstance能夠確保返回的每個(gè)實(shí)例都與所有其他實(shí)例不同。
              5.getType,就像getInstance一樣,但是在工廠方法處于不同的類的時(shí)候使用(子類)。Type表示工廠方法所返回的對(duì)象類型。
              6.newType,就像newInstance一樣,但是在工廠方法處于不同的類的時(shí)候使用(子類)。Type表示工廠方法所返回的對(duì)象類型。
             總之,靜態(tài)工廠方法與公共構(gòu)造器都各有好處,我們需要理解他們各自的長(zhǎng)處。靜態(tài)工廠通常更加合適,因此切記第一反應(yīng)就是提供公有的構(gòu)造器,而不先考慮靜態(tài)工廠。
    部分源碼:
    package com.book.chap2.staticFactory;

    /**
    *
    *服務(wù)接口
    *Service interface
    *
    *@author landon
    *@since 1.6.0_35
    *@version 1.0.0 2012-12-24
    *
    */


    public interface Service
    {

    }


    package com.book.chap2.staticFactory;

    /**
    *
    *服務(wù)提供者接口
    *Service Provider interface
    *
    *@author landon
    *@since 1.6.0_35
    *@version 1.0.0 2012-12-24
    *
    */


    public interface Provider
    {
        Service newService();
    }


    package com.book.chap2.staticFactory;

    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;

    /**
    *
    *非實(shí)例化的類,用來注冊(cè)和訪問服務(wù)
    *
    *@author landon
    *@since 1.6.0_35
    *@version 1.0.0 2012-12-24
    *
    */


    public class Services
    {
       
    private Services()
       
    {
        }

       
       
    //服務(wù)提供者map
        private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
       
    //默認(rèn)的服務(wù)提供者名字
        public static final String DEFAULT_PROVIDER_NAME = "<def>";
       
       
    /**
         *
         * 注冊(cè)默認(rèn)的Provider
         *
         * @param p
        
    */

       
    public static void registerDefaultProvider(Provider p)
       
    {
            registerProvider(DEFAULT_PROVIDER_NAME, p);
        }

       
       
    /**
         *
         * 注冊(cè)Provider
         *
         * @param name
         * @param p
        
    */

       
    public static void registerProvider(String name,Provider p)
       
    {
            providers.put(name, p);
        }

       
       
    //服務(wù)訪問api Service access API
        public static Service newInstance()
       
    {
           
    return newInstance(DEFAULT_PROVIDER_NAME);
        }

       
       
    public static Service newInstance(String name)
       
    {
            Provider p = providers.get(name);
           
           
    if(p == null)
           
    {
               
    throw new IllegalArgumentException("No Provider registered with name:" + name);
            }

           
           
    return p.newService();
        }

    }

    package com.book.chap2.staticFactory;

    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    /**
    *
    *參數(shù)化實(shí)例,使用靜態(tài)工廠,會(huì)使代碼簡(jiǎn)單很多
    *<p>使用類型推斷</p>
    *
    *@author landon
    *@since 1.6.0_35
    *@version 1.0.0 2012-12-26
    *
    */


    public class TypeInference
    {
       
    /**
         *
         * 使用類型推斷的初始化HashMap方式
         *
         * @return
        
    */

       
    public static <K,V> HashMap<K, V>  newInstance()
       
    {
           
    return new HashMap<K, V>();
        }

       
       
    public static void main(Stringargs)
       
    {
           
    //普通方式初始化Map
            Map<String, List<String>> commonMap = new HashMap<String, List<String>>();
           
    //類型推斷的初始化方式
            Map<String, List<String>> inferMap = TypeInference.newInstance();
        }

    }

    posted on 2013-03-15 14:57 landon 閱讀(2342) 評(píng)論(2)  編輯  收藏 所屬分類: ProgramBook

    FeedBack:
    # re: Effective Java 2nd筆記1:序言&考慮使用靜態(tài)工廠方法代替構(gòu)造器
    2013-03-15 16:18 | 全自動(dòng)端子機(jī)
    博客風(fēng)格挺好 圍觀下  回復(fù)  更多評(píng)論
      
    # re: Effective Java 2nd筆記1:序言&考慮使用靜態(tài)工廠方法代替構(gòu)造器
    2013-03-16 10:45 | 背道而馳
    我最近也在看這本書,不過很多地方看的半懂不懂的!!!  回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 亚洲性天天干天天摸| 亚洲精品制服丝袜四区| 国产极品美女高潮抽搐免费网站| 免费鲁丝片一级观看| 免费v片视频在线观看视频| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 国产亚洲一卡2卡3卡4卡新区 | 久久久久国产精品免费看| 亚洲第一网站免费视频| 大学生a级毛片免费观看| 亚洲国产综合精品中文字幕| GOGOGO高清免费看韩国| 青青草原1769久久免费播放| 国产成人A在线观看视频免费| 免费成人av电影| 亚洲国产成人一区二区三区| 亚洲乱码卡三乱码新区| 理论片在线观看免费| 亚欧日韩毛片在线看免费网站| 午夜精品在线免费观看| 亚洲精品美女久久久久99| 亚洲一区免费在线观看| 一个人免费观看视频在线中文| 亚洲成人在线免费观看| 国产无遮挡色视频免费视频| 亚洲国产精品高清久久久| 亚洲中文字幕无码久久2020 | 999久久久免费精品播放| 免费看又黄又无码的网站| 午夜小视频免费观看| 亚洲国产精品乱码一区二区| 亚洲国产精品99久久久久久| 久9热免费精品视频在线观看| 免费看美女让人桶尿口| 亚洲va中文字幕无码久久不卡| 亚洲中文字幕乱码AV波多JI| 久久黄色免费网站| 无码国产亚洲日韩国精品视频一区二区三区 | 中文字幕免费在线看电影大全| 9久9久女女免费精品视频在线观看| 性感美女视频免费网站午夜|