1. 程式人生 > >Java學習--設計模式

Java學習--設計模式

設計模式是一些優秀的軟體開發人員在開發時經驗的積累。它代表了最佳的實踐。讓我們的程式碼實現特定的目的,在結構上更加優秀。
一、單例模式
單例模式是指一個類只能有一個例項,不能再建立更多的例項
第一 種是餓漢式

public class Singleton1 {
     // 讓構造方法私有,別人就沒法建立此類的例項了
    private Singleton1() {
    }
     //自己建立這個例項
    private static final Singleton1 ME = new Singleton1();
     //獲取唯一例項
    public static Singleton1 getInstance() {
        return ME;
    }
}

第二種是懶漢式

public class Singleton2 {
    private Singleton2() {
    }
    private static Singleton2 ME;
    public static synchronized Singleton2 getInstance() {
        // 當一次呼叫時ME == null為真, 當後續呼叫時ME == null為假,就不會執行建立物件的操作了
        if (ME == null) {
            ME = new Singleton2();
        }
        return ME;
    }
}

上述兩種單例模式的區別在於:
餓漢式是一開始就建立好例項;懶漢式是用時才建立例項
第三種使用列舉實現(餓漢式)

public enum Singleton3 {
    ME;
    public void m1() {
    }
}

第四種使用靜態內部類實現(懶漢式)

public class Singleton4 {
    private Singleton4() {
    }
    // holder 擁有, 由靜態內部類建立了他的唯一例項
    private static class Holder {
        static Singleton4 ME = new Singleton4();
    }
    public static Singleton4 getInstance() {
        return Holder.ME;
    }
}

注:
破壞單例的辦法:
反射可以呼叫私有構造
反序列化可以破壞單例 (可以阻止)
二、享元模式 flyweight
享元模式是提倡重用已有的物件,而不是建立新的物件。

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

三、原型模式 prototype

根據已有物件來建立新的物件, 克隆
使用場景,當物件屬性很多,希望新的物件的大部分屬性從原有物件複製而來。

四、建造器模式 Builder

通過建造起模式可以使建立物件時呼叫構造方法更加靈活。
適用於有多個可省引數的構造方法。

五、迭代器模式 iterator

定義:以一種一致的對集合內的元素進行遍歷,而不用在乎集合內的資料結構
ArrayList 陣列
LinkedList 連結串列
HashSet 陣列+連結串列
TreeSet 二叉搜尋樹-》紅黑樹

六、策略模式 (Strategy)
Java 集合或陣列的排序演算法
基本型別 雙基點快速排序方法
物件型別 TimSort (早期使用歸併排序)
規模小 插入排序

public class TestStrategy {

    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("zhangsan", 18));
        list.add(new Student("lisi", 20));
        list.add(new Student("wangwu", 16));
        list.add(new Student("zhaoliu", 22));
        list.add(new Student("zhaoliu", 20));

        // 按年齡拍
        Collections.sort(list, (a, b) ->  a.getAge() - b.getAge() );
        System.out.println(list);

        // 按名字拍
        Collections.sort(list, (a, b) ->  a.getName().compareTo(b.getName()) );
        System.out.println(list);

        // 先按名字,再按年齡
        Collections.sort(list, (a, b) ->  {
            int x = a.getName().compareTo(b.getName());
            if(x != 0) {
                return x;
            } else {
                return a.getAge() - b.getAge();
            }
        } );
        System.out.println(list);
    }
}

class Student {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Student(String name, int age) {

        this.name = name;
        this.age = age;
    }
}

最後說一下:open close 開閉原則
1.演算法不能改-- 體現的是close原則
2.比較器可以改 – 體現的是open原則