單例模式和策略模式

設計模式

單例模式-singleton

  • Spring的Bean工廠就是單例模式,項目中自己寫的情況越來越少

工程中最常用版本-餓漢式

/**
 * 優點:線程安全
 * 缺點:不管用到與否,類裝載時就完成實例化
 */
public class Singleton_01 {
    private static final Singleton_01 INSTANCE = new Singleton_01();

    private Singleton_01() {};

    public static Singleton_01 getInstance() {
        return INSTANCE;
    }
    public static void main(String[] args) {
        Singleton_01 m1 = Singleton_01.getInstance();
        Singleton_01 m2 = Singleton_01.getInstance();
        System.out.println(m1 == m2);
    }
}

雙重鎖檢查-懶漢式

/**
 * 完美版本
 * 缺點:加鎖帶來效率下降
 * 優點:volatile禁止指令重排序,防止半初始化現象。
 * 優點:雙重檢查保證鎖的粒度更小,且消除重複new對象的問題
 */
public class Singleton_02 {
    private static volatile Singleton_02 INSTANCE; //JIT

    private Singleton_02() {
    }

    public static Singleton_02 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton_02.class) {
            // 第二次檢查如果其他線程完成了初始化,其他線程無法進入
                if(INSTANCE == null) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Singleton_02();
                }
            }
        }
        return INSTANCE;
    }
}

完美版本,但不直觀

package com.mashibing.dp.singleton;

/**
 * 不僅可以解決線程同步,還可以防止反序列化。
 */
public enum Singleton_03 {

    INSTANCE;
    
    public static void main(String[] args) {
        for(int i=0; i<100; i++) {
            new Thread(()->{
               System.out.println(Singleton_03.INSTANCE.hashCode());
            }).start();
        }
    }
}

策略模式-Strategy

  • Java的Comparator接口,該接口只有一個抽象方法compare(T o1, T o2)就是策略模式的一個應用;

修改關閉,擴展開放

  • 實現排序方法,自己實現比較器傳入,就是不同的策略傳入,實現可擴展性,策略模式是封裝的做一件事的不同的方式

Java的Comparator接口策略分析

  1. 策略:這裏是比較策略,類比其他的比如售賣策略等
public interface Comparator<T> {
    int compare(T o1, T o2);
}
  1. 具體策略實現:這裏定義根據對象的id來比較。類比售貨打八折銷售,滿減等策略
        Comparator<User> comparator = new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getId() - o2.getId();
            }
        };
  1. 應用策略:事先定義好策略應用
// 比如list的sort方法,需要傳入比較策略
public static void main(String[] args) {
        List<User> l = new ArrayList<>();
        l.add(new User(2, "zhangsan", "123", "aaaa"));
        l.add(new User(3, "zhangsan", "123", "aaaa"));
        l.add(new User(1, "zhangsan", "123", "aaaa"));

        
        Comparator<User> comparator = new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getId()-o2.getId();
            }
        };

        l.sort(comparator);

    }
    
// list的sort方法對比較策略的應用,事實上是用泛型接收具體類型
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }
  • 策略模式的實質是把具體的實現策略抽離出來,達到可擴展的目的,比如要進行比較,那麼比較策略我們自己指定,“比較”動作可以識別我們傳入的策略,和多態有點相似
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章