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

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

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

    當(dāng)EffectiveJava遇見(jiàn)Guava - 靜態(tài)工廠方法代替構(gòu)造器(規(guī)則1)


    Effective Java中指出,使用靜態(tài)工廠方法代替構(gòu)造器有幾大優(yōu)勢(shì):

    第一大優(yōu)勢(shì) - 他們有名稱。

    多個(gè)構(gòu)造器只能通過(guò)匹配參數(shù)類型的順序不同來(lái)區(qū)分使用哪一個(gè),這樣常常會(huì)導(dǎo)致用戶調(diào)用錯(cuò)誤構(gòu)造器,而靜態(tài)工程方法則不同,可以通過(guò)方法名清晰的指明用意。

    //本例只用來(lái)說(shuō)明第一大優(yōu)勢(shì),請(qǐng)不要糾結(jié)其它問(wèn)題 
    public class Foo {
    Set<Bar> bars;
    List<Car> cars;
    //構(gòu)造器1
    private Foo(Set<Bar> bars) {
    this.bars = bars;
    }
    //構(gòu)造器2
    private Foo(List<Car> cars) {
    this.cars = cars;
    }
    //構(gòu)造器3
    private Foo(Set<Bar> bars, List<Car> cars) {
    this.bars = bars;
    this.cars = cars;
    }
    //靜態(tài)工廠方法1
    public static Foo newInstanceByBar(){
    return new Foo(new HashSet<Bar>());
    }
    //靜態(tài)工廠方法2
    public static Foo newInstanceByCar(){
    return new Foo(new ArrayList<Car>());
    }
    //靜態(tài)工廠方法3
    public static Foo newInstanceByAll(){
    return new Foo(new HashSet<Bar>(),new ArrayList<Car>());
    }
    public static void main(String[] args) {
    // 通過(guò)構(gòu)造器創(chuàng)建實(shí)例,不好區(qū)分容易使用錯(cuò)誤
    Foo fbar = new Foo(new HashSet<Bar>());
    Foo fcar = new Foo(new ArrayList<Car>());
    Foo fall = new Foo(new HashSet<Bar>(),new ArrayList<Car>());
    // 通過(guò)靜態(tài)工廠方法可以清晰的用方法名識(shí)別
    Foo fbar_static = Foo.newInstanceByBar();
    Foo fcar_static = Foo.newInstanceByCar();
    Foo fall_static = Foo.newInstanceByAll();
    }
    }
    class Bar {}
    class Car {}

    對(duì)于Guava,并沒(méi)有提供創(chuàng)建靜態(tài)工廠方法的工具,但整個(gè)Guava API到處都是靜態(tài)方法的實(shí)現(xiàn),我們以Guava Collections Framewrok舉例說(shuō)明。

    Guava對(duì)于第一大優(yōu)勢(shì)有很多實(shí)現(xiàn):

    List<Type> exactly100 = Lists.newArrayListWithCapacity(100);
    List<Type> approx100 = Lists.newArrayListWithExpectedSize(100);
    Set<Type> approx100Set = Sets.newHashSetWithExpectedSize(100);

    第二大優(yōu)勢(shì) - 不必在每次調(diào)用他們的時(shí)候都創(chuàng)建一個(gè)新對(duì)象。

    方便對(duì)象重用,還可以確保不可變的不會(huì)存在兩個(gè)相等的實(shí)例,如果a==b那么a.equals.(b)才會(huì)返回true ,如果能保證這一點(diǎn),就可以使用==操作符來(lái)比較對(duì)象,會(huì)有很大的性能提升。

    第三大優(yōu)勢(shì) - 他們可以返回原返回類型的任何子類型的對(duì)象。

    這是一個(gè)非常強(qiáng)大的特性, Effective Java中列舉了API、SPI、服務(wù)提供框架的關(guān)系來(lái)說(shuō)明:

    API(Service Interface): 服務(wù)公共接口 SPI(Service Provider Interface): 服務(wù)提供商接口 SPF(Service Provider Framework): 服務(wù)提供框架

    看例子:

    // 服務(wù)提供框架示意模型 - 服務(wù)API 
    public interface ServiceAPI {
    // 這里是服務(wù)指定的方法
    }
    // 服務(wù)提供框架示意模型 - 服務(wù)SPI
    public interface ServiceSPI {
    ServiceAPI newService();
    }
    // 服務(wù)提供框架示意模型實(shí)現(xiàn)
    // 不可實(shí)例化的類,用來(lái)注冊(cè)創(chuàng)建和提供訪問(wèn)
    public class ServiceFramework {
    private ServiceFramework() {
    }// 強(qiáng)制防止實(shí)例化(規(guī)則4)

    // 映射服務(wù)名到服務(wù)
    private static final ConcurrentMap<String, ServiceSPI> spis = new MapMaker().makeMap();//使用Guava創(chuàng)建
    public static final String DEFAULT_SPI_NAME = "<def>";

    // 默認(rèn)SPI注冊(cè)API
    public static void registerDefaultSPI(ServiceSPI spi) {
    registerSPI(DEFAULT_SPI_NAME, spi);
    }

    // 指定SPI注冊(cè)API
    public static void registerSPI(String name, ServiceSPI spi) {
    spis.put(name, spi);
    }

    // 服務(wù)訪問(wèn)API
    public static ServiceAPI newInstance() {
    return newInstance(DEFAULT_SPI_NAME);
    }
    public static ServiceAPI newInstance(String name) {
    ServiceSPI spi = spis.get(name);
    if(spi == null)
    throw new IllegalArgumentException(
    "No provider registered with name: " + name);
    return spi.newService();
    }
    }
    Note
    靜態(tài)工程方法返回的對(duì)象所屬的類,在編寫(xiě)這個(gè)包含靜態(tài)工廠方法的類時(shí)可以不必存在。上面的例子在編寫(xiě)ServiceFramework類時(shí),ServiceAPI的實(shí)現(xiàn)類并不存在。這大大增加了框架的靈活性。

    現(xiàn)在編寫(xiě)客戶端測(cè)試程序

    // 簡(jiǎn)單的服務(wù)提供框架測(cè)試程序 
    public class Test {
    public static void main(String[] args) {
    // 服務(wù)提供商執(zhí)行下面的注冊(cè)
    ServiceFramework.registerDefaultSPI(DEFAULT_PROVIDER);
    ServiceFramework.registerSPI("comp", COMP_PROVIDER);
    ServiceFramework.registerSPI("armed", ARMED_PROVIDER);
    // 客戶端執(zhí)行下面的創(chuàng)建
    ServiceAPI s1 = ServiceFramework.newInstance();
    ServiceAPI s2 = ServiceFramework.newInstance("comp");
    ServiceAPI s3 = ServiceFramework.newInstance("armed");
    System.out.printf("%s, %s, %s%n", s1, s2, s3);
    }
    private static ServiceSPI DEFAULT_PROVIDER = new ServiceSPI() {
    public ServiceAPI newService() {
    return new ServiceAPI() {
    @Override
    public String toString() {
    return "默認(rèn)服務(wù)";
    }
    };
    }
    };
    private static ServiceSPI COMP_PROVIDER = new ServiceSPI() {
    public ServiceAPI newService() {
    return new ServiceAPI() {
    @Override
    public String toString() {
    return "Complementary 服務(wù)";
    }
    };
    }
    };
    private static ServiceSPI ARMED_PROVIDER = new ServiceSPI() {
    public ServiceAPI newService() {
    return new ServiceAPI() {
    @Override
    public String toString() {
    return "Armed 服務(wù)";
    }
    };
    }
    };
    }

    //輸出如下 認(rèn)務(wù), Complementary 務(wù), Armed 務(wù)

    第四大優(yōu)勢(shì) - 在創(chuàng)建參數(shù)化類型實(shí)例的時(shí)候,他們使代碼變得更加簡(jiǎn)潔。

    在JDK7之前,我們創(chuàng)建一個(gè)Collections大致是這么做的:

    List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<TypeThatsTooLongForItsOwnGood>();

    JDK7發(fā)布以后,我們可以簡(jiǎn)化成這樣:

    List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<>();

    但是Guava還是寧愿使用靜態(tài)工程方法,因?yàn)檎娴姆浅7奖悖?/p>

    Set<Type> copySet = Sets.newHashSet(elements); 
    List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");

    靜態(tài)工程方法的缺點(diǎn)

    • 類如果不含公有的或者受保護(hù)的構(gòu)造器,就不能被子類化,這也許會(huì)因禍得福,因?yàn)樗膭?lì)開(kāi)發(fā)人員使用復(fù)合,而不是繼承。

    • 他們與其他的靜態(tài)方法實(shí)際上沒(méi)有任何區(qū)別 如果API文檔沒(méi)有明確的說(shuō)明這是一個(gè)靜態(tài)工程方法,就會(huì)很難識(shí)別出來(lái)。遵循標(biāo)準(zhǔn)的命名規(guī)范習(xí)慣,可以彌補(bǔ)這一劣勢(shì),下面列出一些慣用命名:

      • valueOf - 這樣的靜態(tài)工廠方法實(shí)際上是類型轉(zhuǎn)換

      • of - valueOf的簡(jiǎn)潔方式

      • getInstance - 返回實(shí)例通過(guò)方法參數(shù)描述,對(duì)于單例,該方法沒(méi)有參數(shù),并返回唯一的實(shí)例

      • newInstance - 與getInstance不同的是,它返回的實(shí)例與所有其它實(shí)例都是不同的

      • getType - 像getInstance一樣,但是在工廠方法處于不同的類中的時(shí)候使用。Type表示i返回對(duì)象類型

      • newType - 像newInstance一樣,但是在工廠方法處于不同的類中的時(shí)候使用。Type表示i返回對(duì)象類型

    2013-05-29

    posted on 2013-05-30 17:09 kuuyee 閱讀(3900) 評(píng)論(1)  編輯  收藏 所屬分類: JEE

    評(píng)論

    # re: 當(dāng)EffectiveJava遇見(jiàn)Guava - 靜態(tài)工廠方法代替構(gòu)造器(規(guī)則1) 2013-05-31 12:41 11

    發(fā)現(xiàn)了:

    The project was not built since its build path is incomplete.

    Cannot find the class file for com.aaap.workflow.engine.WorkFlowSupportSes. Fix the build path then try building this project

    The type com.aaap.workflow.services.ForwardNodesFacadeSes cannot be resolved. It is indirectly referenced from required .class

    意思是“工程需要用的包沒(méi)有引導(dǎo)入完全,沒(méi)有找到需要的類文件,請(qǐng)修改buildPath后重新編譯項(xiàng)目”

    和同事一比對(duì),果然少引入了若干包,引入缺少的幾個(gè)包后,重新編譯,Problems視圖里提示的“”信息沒(méi)了。

    現(xiàn)在勾選了重新編譯,再修改,保存,編譯一閃而過(guò)~~ 正常啦!!
      回復(fù)  更多評(píng)論   

    導(dǎo)航

    <2013年5月>
    2829301234
    567891011
    12131415161718
    19202122232425
    2627282930311
    2345678

    統(tǒng)計(jì)

    隨筆分類(139)

    Linux內(nèi)核

    搜索

    •  

    積分與排名

    • 積分 - 320429
    • 排名 - 178

    最新評(píng)論

    閱讀排行榜

    主站蜘蛛池模板: 噜噜嘿在线视频免费观看| 国产成人精品免费视频软件| 亚洲宅男精品一区在线观看| 免费看美女让人桶尿口| 精选影视免费在线 | 亚洲av日韩av高潮潮喷无码| 日本特黄特色aa大片免费| 亚洲乱亚洲乱妇无码麻豆| 99久热只有精品视频免费看| 亚洲日韩国产二区无码 | 免费毛片在线视频| www一区二区www免费| 亚洲激情校园春色| 亚洲综合色区在线观看| 免费v片在线观看视频网站| 亚洲精品制服丝袜四区| 男人的好看免费观看在线视频| 国产日韩精品无码区免费专区国产 | 久久这里只有精品国产免费10| 国产精品极品美女自在线观看免费 | 亚洲va中文字幕无码| 免费国产成人高清在线观看网站| 国产99精品一区二区三区免费| 亚洲一区二区三区在线观看蜜桃| 久久亚洲欧洲国产综合| 免费看美女被靠到爽的视频| 日本免费一区二区三区四区五六区 | 亚洲综合av一区二区三区| 亚洲av午夜福利精品一区人妖| 国产一级淫片免费播放| 特级毛片aaaa级毛片免费| 亚洲人成电影青青在线播放| 亚洲啪啪AV无码片| 一本色道久久88亚洲综合| jyzzjyzz国产免费观看| 2020亚洲男人天堂精品| 亚洲黄色在线视频| 亚洲精品乱码久久久久久| 亚洲人午夜射精精品日韩| 国产视频精品免费| 成全视频免费高清|