天天看點

JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類

JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類

版權聲明:轉載必須注明本文轉自程式員杜鵬程的部落格:http://blog.csdn.net/m366917

這篇我們來學習面向對象思想設計原則及常見的設計模式

面向對象思想設計原則

在實際的開發中,我們要想更深入的了解面向對象思想,就必須熟悉前人總結過的面向對象的思想的設計原則,那麼都有哪些原則呢,我們就來了解一下
  • 單一職責原則
    • 其實就是開發人員經常說的”高内聚,低耦合”
  • 開閉原則
    • 核心思想是:一個對象對擴充開放,對修改關閉。其實開閉原則的意思就是:對類的改動是通過增加代碼進行的,而不是修改現有代碼。
  • 裡氏替換原則
    • 核心思想:在任何父類出現的地方都可以用它的子類來替代。其實就是說:同一個繼承體系中的對象應該有共同的行為特征。
  • 依賴注入原則
    • 核心思想:要依賴于抽象,不要依賴于具體實作。
  • 接口分離原則
    • 核心思想:不應該強迫程式依賴它們不需要使用的方法。
  • 迪米特原則
    • 核心思想:一個對象應當對其他對象盡可能少的了解
      這些原則呢,我們在平時開發中可以用到,做一些大一點的項目,就要考慮用到這些思想,下面,我簡單的介紹一下這些原則的核心思想,大家做以了解,如果要将這些原則運用到自己項目中,還要自己更加深入的學習、了解、運用。

設計模式

設計模式在我們開發中還是經常用到的,那麼,下面我們來學習一下
  • 設計模式概述
    • 設計模式(Design pattern)是一套被反複使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人了解、保證代碼可靠性。
    • 設計模式不是一種方法和技術,而是一種思想
    • 設計模式和具體的語言無關,學習設計模式就是要建立面向對象的思想,盡可能的面向接口程式設計,低耦合,高内聚,使設計的程式可複用
    • 學習設計模式能夠促進對面向對象思想的了解,反之亦然。它們相輔相成
  • 設計模式的幾個要素:
    • 名字 必須有一個簡單,有意義的名字
    • 問題 描述在何時使用模式
    • 解決方案 描述設計的組成部分以及如何解決問題
    • 效果 描述模式的效果以及優缺點
  • 設計模式的分類
    • 建立型模式 對象的建立
    • 結構型模式 對象的組成(結構)
    • 行為型模式 對象的行為

    建立型模式:簡單工廠模式,工廠方法模式,抽象工廠模式,建造者模式,原型模式,單例模式。(6個)

    結構型模式:外觀模式、擴充卡模式、代理模式、裝飾模式、橋接模式、組合模式、享元模式。(7個)

    行為型模式:模版方法模式、觀察者模式、狀态模式、職責鍊模式、指令模式、通路者模式、政策模式、備忘錄模式、疊代器模式、解釋器模式。(10個)

設計模式的分類雖然很多,但是我們平時能用到的也就下面幾種而已,是以不要被它這麼多模式所吓倒。

  • 常見的設計模式
    • 簡單工廠模式和工廠方法模式(接口)
    • 模版設計模式(抽象類)
    • 裝飾設計模式(IO流)
    • 單例設計模式(多線程)
    • 擴充卡模式(GUI)
      下面我們就來學習我們常用的幾種設計模式,讓大家掌握,熟悉,并運用到自己的項目中,學會學以緻用。

簡單工廠模式

  • 簡單工廠模式概述
    • 又叫靜态工廠方法模式,它定義一個具體的工廠類負責建立一些類的執行個體
      我們來寫一個簡單的例子來解釋簡單工廠模式
/*
 * 抽象的動物類,裡面有抽象的方法
 */
public abstract class Animal {
    public abstract void eat();
}

/*
 * 具體的動物貓繼承抽象動物類,重寫抽象方法
 */
public class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("貓吃魚");
    }
}

/*
 * 具體的動物狗繼承抽象動物類,重寫抽象方法
 */
public class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

/*
 * 動物工廠類,可以造貓和狗
 */
public class AnimalFactory {

    private AnimalFactory() {
    }
    public static Animal createAnimal(String type) {
        if ("dog".equals(type)) {
            return new Dog();
        } else if ("cat".equals(type)) {
            return new Cat();
        } else {
            return null;
        }
    }
}

/*
 *  測試類
 */
public class AnimalDemo {
    public static void main(String[] args) {

        // 工廠有了後,通過工廠給造
        Animal a = AnimalFactory.createAnimal("dog");
        a.eat();
        a = AnimalFactory.createAnimal("cat");
        a.eat();

        // NullPointerException
        a = AnimalFactory.createAnimal("pig");
        if (a != null) {
            a.eat();
        } else {
            System.out.println("對不起,暫時不提供這種動物");
        }
    }
}
           
運作程式控制台輸出
JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類

以前我們在學代碼的時候,不會去建立這個動物的工廠類,而是直接具體類的調用,比如:

Dog d = new Dog();
        d.eat();
        Cat c = new Cat();
        c.eat();
           

現在我們運用了簡單工廠模式後,就不用每次用的時候去new對象,而是直接去調用這個工廠類裡面的具體方法,它會給我們傳回一個已經new好的對象。那麼這樣做有什麼有缺點呢,我們來總結一下。

  • 優點
    • 用戶端不需要在負責對象的建立,進而明确了各個類的職責
  • 缺點
    • 這個靜态工廠類負責所有對象的建立,如果有新的對象增加,或者某些對象的建立方式不同,就需要不斷的修改工廠類,不利于後期的維護
      當我們要用一個模式時,當這個模式的優點大于缺點的時候,我們就可以使用了,但是在簡單工廠模式中我們可以看到它的缺點,當我們有新的對象增加時,就要不斷的修改工廠類,是以不推薦大家用簡單工廠模式,那麼我們要用什麼呢,這就引出了我們要學的下一個知識點工廠方法模式

工廠方法模式

  • 工廠方法模式概述
    • 工廠方法模式中抽象工廠類負責定義建立對象的接口,具體對象的建立工作由繼承抽象工廠的具體類實作。
      我們就來用工廠方法模式對上面的那個例子進行改進
/*
 * 抽象的動物類,裡面有抽象的方法
 */
public abstract class Animal {
    public abstract void eat();
}

/*
 *  工廠類接口,裡面有抽象的創造動物的方法
 */
public interface Factory {
    public abstract Animal createAnimal();
}

/*
 * 具體的貓類繼承抽象動物類,重寫抽象方法
 */
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("貓吃魚");
    }
}

/*
 *  貓工廠類實作工廠類并實作它的抽象方法,傳回一個貓對象
 */
public class CatFactory implements Factory {

    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}

/*
 * 具體的狗類繼承抽象動物類,重寫抽象方法
 */
public class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

/*
 *  狗工廠類實作工廠類并實作它的抽象方法,傳回一個狗對象
 */
public class DogFactory implements Factory {

    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}

/*
 * 測試類
 */
public class AnimalDemo {
    public static void main(String[] args) {
        // 需求:我要買隻狗
        Factory f = new DogFactory();
        Animal a = f.createAnimal();
        a.eat();

        //需求:我要買隻貓
        f = new CatFactory();
        a = f.createAnimal();
        a.eat();
    }
}
           

運作程式,控制台會輸出,狗吃肉 貓吃魚

我們仔細觀察用工廠方法模式比比簡單工廠模式多了幾個類,但是當我們在需要一種動物豬時,我們就不用去修改工廠類裡面的代碼了,隻需用建立一個豬類繼承抽象動物類,重寫抽象方法,再建立一個豬的工廠類實作工廠類并實作它的抽象方法,就可以了。代碼具有很強的維護性和擴充性,那麼我們來分析一下工廠方法模式的優缺點。

  • 優點
    • 用戶端不需要在負責對象的建立,進而明确了各個類的職責,如果有新的對象增加,隻需要增加一個具體的類和具體的工廠類即可,不影響已有的代碼,後期維護容易,增強了系統的擴充性
  • 缺點
    • 需要額外的編寫代碼,增加了工作量
      我們可以看到工廠方法模式的優點明顯大于缺點,是以推薦大家使用。

單例設計模式

  • 單例設計模式概述
    • 單例模式就是要確定類在記憶體中隻有一個對象,該執行個體必須自動建立,并且對外提供。
如何實作類在記憶體中隻有一個對象呢?
  • 構造私有
  • 本身提供一個對象
  • 通過公共的方法讓外界通路

那麼我們就來學習單例模式中餓漢式和懶漢式 這兩種模式,并做以比較

餓漢式

餓漢式:類一加載就建立對象
public class Student {
    // 構造私有
    private Student() {
    }

    // 自己造一個對象
    // 靜态方法隻能通路靜态成員變量,加靜态
    // 為了不讓外界直接通路修改這個值,加private
    private static Student s = new Student();

    // 提供公共的通路方式
    // 為了保證外界能夠直接使用該方法,加靜态
    public static Student getStudent() {
        return s;
    }
}

public class StudentDemo {
    public static void main(String[] args) {

        // 通過單例得到對象
        Student s1 = Student.getStudent();
        Student s2 = Student.getStudent();
        System.out.println(s1 == s2);   //true


    }
}
           
運作程式,控制台會輸出true,說明我們用單例模式的餓漢式確定類在記憶體中隻有一個對象,他的特點就是類一加載就建立對象,可以在代碼中Student類中展現到。那麼我們怎樣才能在用這個對象的時候才去建立它呢,我們就要來看下懶漢式了。

懶漢式

懶漢式:用對象的時候,才去建立對象
public class Teacher {
    private Teacher() {
    }

    private static Teacher t = null;

    public static Teacher getTeacher() {    
        if (t == null) {
            t = new Teacher();//當我們去用這個對象的時候才去建立它
        }
        return t;
    }
}

public class TeacherDemo {
    public static void main(String[] args) {

        Teacher t1 = Teacher.getTeacher();
        Teacher t2 = Teacher.getTeacher();
        System.out.println(t1 == t2); //true

    }
}
           

單例模式的餓漢式和懶漢式是不是很容易了解呢,那麼我們什麼時候用餓漢式什麼時候用懶漢式呢?

我們就來總結一下

餓漢式懶漢式比較

餓漢式我們經常在開發中使用,因為餓漢式是不會出問題的單例模式

懶漢式我們在面試中回答用,因為懶漢式可能會出問題的單例模式。

面試主要面兩個思想,分别是:

  • 懶加載思想(延遲加載)
  • 線程安全問題(就要考慮下面3個方面)
    • 是否多線程環境
    • b:是否有共享資料
    • c:是否有多條語句操作共享資料

      如果都是,就會存線上程的安全問題,我們上面的懶漢式代碼是不完整的,應該給對象中的方法加上synchronized關鍵字,這樣才算完整

public synchronized static Teacher getTeacher() {   
        if (t == null) {
            t = new Teacher();
        }
        return t;
    }
           

Runtime類

我們在這裡為什麼要說Runtime類,因為它在java中的設計就是按照單例模式之餓漢式設計的,我們來看一段源碼

class Runtime {
            private Runtime() {}
            private static Runtime currentRuntime = new Runtime();
            public static Runtime getRuntime() {
                return currentRuntime;
            }
      }
           

我們來了解一下他的概述

  • 每個 Java 應用程式都有一個 Runtime 類執行個體,使應用程式能夠與其運作的環境相連接配接。可以通過 getRuntime 方法擷取目前運作時。
  • 應用程式不能建立自己的 Runtime 類執行個體。
  • Runtime類使用
    • public Process exec(String command)

      這個類是用來幹什麼的呢,它可以幫助我們運作DOS指令,比如打開記事本、電腦之類的電腦工具,當然也有更多的功能,我們來體驗一下

public class RuntimeDemo {
    public static void main(String[] args) throws IOException {
        Runtime r = Runtime.getRuntime();

         r.exec("notepad");

    }
}
           
運作程式會幫我們打開記事本
r.exec("shutdown -s -t 1000");
           
這個指令會幫我們把電腦定時關機,上面的意思就是1000秒以後關機,我們來看運作後的效果圖
JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類
那麼怎麼取消呢?
r.exec("shutdown -a");
           
哈哈,這樣就取消了
JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類JAVA基礎再回首(二十六)——面向對象思想設計原則、設計模式、簡單工廠模式、工廠方法模式、單例設計模式之餓漢式和懶漢式、Runtime類

下面我們來說說模版設計模式和裝飾設計模式,這個大家作為了解,想要深入學習的話,可以在網上查閱相關的資料進行學習

模版設計模式

  • 模版設計模式概述
    • 模版方法模式就是定義一個算法的骨架,而将具體的算法延遲到子類中來實作
  • 優點
    • 使用模版方法模式,在定義算法骨架的同時,可以很靈活的實作具體的算法,滿足使用者靈活多變的需求
  • 缺點
    • 如果算法骨架有修改的話,則需要修改抽象類

我們可以在計算程式的運作時間中應用模版設計模式,在代碼中我們隻需用改變要計算的代碼就可以了,把計算的時間設計成一個模版。

裝飾設計模式

  • 裝飾設計模式概述
    • 裝飾模式就是使用被裝飾類的一個子類的執行個體,在用戶端将這個子類的執行個體交給裝飾類。是繼承的替代方案
  • 優點
    • 使用裝飾模式,可以提供比繼承更靈活的擴充對象的功能,它可以動态的添加對象的功能,并且可以随意的組合這些功能
  • 缺點
    • 正因為可以随意組合,是以就可能出現一些不合理的邏輯

在IO流中的裝飾模式應用

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(System.out)));
           
好了,我們設計模式就将這麼多了,最後呢,我上傳一本書《java與模式》有興趣的你可以下載下傳看看

歡迎有興趣的同學加我朋友的QQ群:點選直接加群555974449 請備注:java基礎再回首我們一起來玩吧。