20.Java設計模式

20.Java設計模式
轉載請保留原文鏈接: http://dashidan.com/article/java/basic/20.html

軟件設計領域的四位世界級大師Gang Of Four (GoF):Erich Gamma, Richard Helm, Ralph Johnson,John Vlissides合著了一本非常著名的書《Design Patterns - Elements of Reusable Object-Oriented Software》翻譯的中文名爲《設計模式:可複用面向對象軟件的基礎》.書中提出了23種基本設計模式,從理論高度提煉並規範了設計模式,對面向對象軟件設計產生了巨大影響.

19-1

① 設計模式簡介

總體來說設計模式分爲三大類:
創建型模式,共五種:工廠模式、抽象工廠模式、單例模式、建造者模式、原型模式.
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式.
行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式.

有些設計模式我個人認爲,不是很具象, 就像星座一樣抽象概念居多,導致應用場景不明確. 所以不希望他們佔用我過多的腦容量和時間.只挑選幾個含金量高, 模型具象, 應用場景廣泛的模式來介紹. 以下這幾個都是非常值得花時間去熟悉的模式.

② 單例模式

單例模式即是隻產生一個對象的模式.在Java中,每次使用new關鍵字, 就會產生一個新的對象. 有時我們需要只有一個對象產生, 比如一些管理類, 全局管理其它模塊時, 這個管理類適合採用單例模式.

普通的單例模式分爲2種, 懶漢式和餓漢式.懶漢式比較懶, 用到的時候才創建對象, 餓漢式不講理, 你用不用我都創建好放着.

secret

普通單例模式的祕籍:
* 將構造函數定義爲私有private, 只能在本類中創建, 不能被繼承.
* 通過privatestatic關鍵字定義一個私有並且靜態的本類實例對象, 保證內存中只有1個實例, 並且只有本類能調用.
* 公開一個獲得本類實例的靜態方法, 來獲取這個實例, 保證每次得到的實例都是同一個, 來實現單例模式.

列出4種常用的單例模式的寫法, 推薦第4種. 第4種是通過內部類實現, 高效且線程安全. 記住這個好了, 其他的可以忘.

1.懶漢式

/**
 * 懶漢式單例模式
 */
class Singleton1 {

    private static Singleton1 singleton1;

    private Singleton1() {

    }

    public static Singleton1 getInstance() {
        if (null == singleton1) {
            singleton1 = new Singleton1();
        }
        return singleton1;
    }
}

2.餓漢式

/**
 * 餓漢式單例模式
 */
class Singleton2 {

    private static Singleton2 singleton2 = new Singleton2();

    private Singleton2() {
    }

    public static Singleton2 getInstance() {
        return singleton2;
    }
}

3.線程安全的懶漢式

/**
 * 線程安全懶漢式單例模式
 */
class Singleton3 {

    private static Singleton3 singleton3;

    private Singleton3() {

    }

    public static synchronized Singleton3 getInstance() {
        if (null == singleton3) {
            singleton3 = new Singleton3();
        }
        return singleton3;
    }
}

4.內部類線程安全單例模式

這種方式利用java的final關鍵字特性, 一旦賦值無法改變.線程安全,效率高推薦方式.

/**
 * 內部類線程安全單例模式
 */
class Singleton4 {

    private static class SingletonHolder {
        public final static Singleton4 instance = new Singleton4();
    }

    public static Singleton4 getInstance() {
        return SingletonHolder.instance;
    }
}

③ 工廠模式

工廠模式本質是通過條件語句,根據不同的條件創建不同的對象.通常情況下, 產生的對象繼承自同一個父類, 工廠類提供的方法返回的類型爲父類對象類型.達到對象封裝的作用.

代碼示例:

package com.dashidan.lesson19;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇:  19.Java設計模式
 * 工廠模式
 */
public class Demo2 {
    public static void main(String[] args) {
        /** 傳入需要生產的產品類型*/
        Product product = Factory.getProduct(1);
        /** 打印產品信息*/
        product.info();
    }
}

/**
 * 工廠模式
 * 根據不同的類型,生產不同的產品
 */
class Factory {
    public static Product getProduct(int type) {
        switch (type) {
            case 1:
                return new Product1();
            case 2:
                return new Product2();
        }
        return null;
    }
}

/**
 * 產品的父類是抽象類,提供一個info方法
 */
abstract class Product {

    public abstract void info();
}

/**
 * 產品Product1繼承自父類Product
 */
class Product1 extends Product {
    @Override
    public void info() {
        System.out.println("Product1 info.");
    }
}

/**
 * 產品Product2繼承自父類Product
 */
class Product2 extends Product {
    @Override
    public void info() {
        System.out.println("Product2 info.");
    }
}

輸出:

Product1 info.

④ 觀察者模式

觀察者模式(也稱爲發佈(publish)-訂閱(Subscribe)模式、模型-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式).是一個非常棒的降低代碼耦合度的方式.

secret

觀察者模式的祕籍:
* 觀察者在發佈者對象上註冊消息偵聽, 加入消息偵聽列表
* 發佈者遍歷消息偵聽列表, 調用觀察者方法處理消息
* 不同的觀察者對象通常繼承同一個觀察者接口, 通過接口方法統一處理

通常用在一對多或者多對多的場景中, 一個對象數據變化了, 需要通知其他對象的場景. 比如ActionScript3語言底層的事件冒泡機制, 就是採用觀察者模式設計.

代碼示例:

package com.dashidan.lesson19;


import java.util.ArrayList;

/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇:  19.Java設計模式
 * 觀察者模式
 */
public class Demo3 {
    public static void main(String[] args) {
        /** 初始化發佈者和觀察者*/
        Publisher publisher = new Publisher();
        Observer1 observer1 = new Observer1();
        Observer2 observer2 = new Observer2();
        /** 加入2個觀察者到發佈者的消息偵聽隊列*/
        publisher.addObserver(observer1);
        publisher.addObserver(observer2);
        /** 通知觀察者*/
        publisher.notifyAllObserver();
    }
}

/**
 * 發佈者
 */
class Publisher {

    /**
     * 發佈者的消息偵聽隊列
     */
    ArrayList<IObserver> observers = new ArrayList<>();

    /**
     * 加入消息偵聽隊列
     */
    public void addObserver(IObserver iObserver) {
        System.out.println("加入觀察者");
        observers.add(iObserver);
    }

    /**
     * 通知偵聽隊列中所有的觀察者
     */
    public void notifyAllObserver() {
        for (IObserver iObserver : observers) {
            System.out.println("通知觀察者");
            iObserver.action();
        }
    }
}

/**
 * 觀察者接口
 */
interface IObserver {
    void action();
}

/**
 * 觀察者Observer1類
 */
class Observer1 implements IObserver {
    @Override
    public void action() {
        System.out.println("Observer1 action.");
    }
}

/**
 * 觀察者Observer2類
 */
class Observer2 implements IObserver {
    @Override
    public void action() {
        System.out.println("Observer2 action.");
    }
}

輸出:

加入觀察者
加入觀察者
通知觀察者
Observer1 action.
通知觀察者
Observer2 action.

⑤ 相關文章

Java從入門到精通

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章