<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          單例模式哪些不得不說的場景

          共 2244字,需瀏覽 5分鐘

           ·

          2020-11-19 21:26

          點擊上方「藍字」關(guān)注我們

          0x01:單例模式被破壞

          • 反射技術(shù)非常強大,可以通過setAccessible()來修改構(gòu)造器,字段,方法的可見性。單例模式的構(gòu)造方法是私有的,如果將其可見性設(shè)為public,那么將無法控制對象的創(chuàng)建。

          public?class?Singleton?{

          private?static?Singleton?instance?=?new?Singleton();???

          ????private?Singleton()?{}?

          ????public?static?Singleton?getInstance()?{
          ????????return?instance;
          ????}
          }

          通過以下代碼,即可構(gòu)建兩個不同的對象

          public?class?SingletonCmd?{

          ?public?static?void?main(String[]?args)?throws?Exception{
          ????????Singleton?singleton?=?Singleton.getInstance();
          ????????Constructor?constructor?=?Singleton.class.getDeclaredConstructor();
          ????????constructor.setAccessible(true);
          ????????Singleton?newSingleton??=?constructor.newInstance();

          ????????System.out.println(singleton.hashCode());
          ????????System.out.println(newSingleton.hashCode());

          ????}

          }

          另外,克隆、序列化都可能導(dǎo)致單例模式被破壞。


          0x02:防止反射破壞單例模式

          主要通過在單例對象里添加一個標(biāo)識位,在創(chuàng)建了一個時,改變該標(biāo)識位。

          public?class?Singleton?{

          ??private?static??Boolean?flag?=?Boolean.FALSE;

          ??private?static?Singleton?singleton?=?null;

          ??private?Singleton()?{
          ??????if?(!flag)?{
          ??????????synchronized?(Singleton.class)?{
          ??????????????if(!flag){
          ??????????????????flag?=?true;
          ??????????????}else{
          ??????????????????throw?new?RuntimeException("正在破壞單例模式");?
          ??????????????}
          ??????????}
          ??????}?else?{
          ??????????throw?new?RuntimeException("正在破壞單例模式");
          ??????}
          ??}

          ??public?static?Singleton?getInstance()?{
          ??????if?(singleton?==?null)?{
          ??????????synchronized?(Singleton.class)?{
          ??????????????if?(singleton?==?null)?{
          ??????????????????singleton?=?new?Singleton();
          ??????????????}
          ??????????}
          ??????}
          ??????return?singleton;
          ??}

          ??public?static?void?main(String[]?args)?throws?Exception?{
          ???? Singleton?s1?=?Singleton.getInstance();
          ????? Class?c1?=?Singleton.class;
          ???? Constructor?constructor?=?c1.getDeclaredConstructor();
          ???? constructor.setAccessible(true);
          ???? Singleton?s2?=?constructor.newInstance();
          ???? System.out.println(s1?==?s2);

          }

          }

          這種實現(xiàn)并不是非常嚴(yán)謹(jǐn),因為既然可以通過反射來獲取構(gòu)造函數(shù)來創(chuàng)建實例了,那么同樣可以通過反射來獲取到定義的flag,那么在利用反射調(diào)用構(gòu)造函數(shù)之前,先獲取到這個flag,將它值重置,那么再次調(diào)用構(gòu)造函數(shù)就不會受到限制了,那這樣實際上就沒有起到防止重復(fù)創(chuàng)建對象的效果。這個另外一個實現(xiàn)方案

          public?class?Singleton?{

          ????private?static?ImmutableBoolean?flag?=?new?ImmutableBoolean();

          ????private?static?Singleton?singleton?=?null;

          ????private?Singleton()?{
          ????????if?(flag.getCount()?<=?0)?{
          ????????????synchronized?(Singleton.class)?{
          ????????????????if?(flag.getCount()?<=?0)?{
          ????????????????????flag.setCount();
          ????????????????}?else?{
          ????????????????????throw?new?RuntimeException("正在破壞單例模式1");
          ????????????????}
          ????????????}
          ????????}?else?{
          ????????????throw?new?RuntimeException("正在破壞單例模式2");
          ????????}
          ????}

          ????public?static?Singleton?getInstance()?{
          ????????if?(singleton?==?null)?{
          ????????????synchronized?(Singleton.class)?{
          ????????????????if?(singleton?==?null)?{
          ????????????????????singleton?=?new?Singleton();
          ????????????????}
          ????????????}
          ????????}
          ????????return?singleton;
          ????}

          ????private?static?class?ImmutableBoolean?{
          ????????private?static?int?count?=?0;

          ????????public?ImmutableBoolean()?{

          ????????}

          ????????public?void?setCount()?{
          ????????????synchronized?(Singleton.class)?{
          ????????????????if?(count?<=?0)?{
          ????????????????????count++;
          ????????????????}?else?{
          ????????????????????throw?new?RuntimeException("counterror");
          ????????????????}
          ????????????}
          ????????}

          ????????public?int?getCount()?{
          ????????????return?count;
          ????????}
          ????}
          }

          定義一個私有的內(nèi)部類,然后用這個內(nèi)部類的屬性來作為flag,這樣外面的其他類就獲取不到這個私有的內(nèi)部類,也就不能改變它的值了,從而保護了單例的實現(xiàn)。

          參考:https://blog.csdn.net/shengfengwuying/article/details/89919386

          掃碼二維碼

          獲取更多精彩

          Java樂園

          有用!分享+在看?


          瀏覽 32
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天堂在线aaa | 欧美精品久久久久久久久爆乳 | 北条麻妃在线一区二区三区 | 日本黄色视屏网站 | 成人开心激情五月 |