轉載請保留原文鏈接: 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種基本設計模式,從理論高度提煉並規範了設計模式,對面向對象軟件設計產生了巨大影響.
① 設計模式簡介
總體來說設計模式分爲三大類:
創建型模式,共五種:工廠模式、抽象工廠模式、單例模式、建造者模式、原型模式.
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式.
行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式.
有些設計模式我個人認爲,不是很具象, 就像星座一樣抽象概念居多,導致應用場景不明確. 所以不希望他們佔用我過多的腦容量和時間.只挑選幾個含金量高, 模型具象, 應用場景廣泛的模式來介紹. 以下這幾個都是非常值得花時間去熟悉的模式.
② 單例模式
單例模式即是隻產生一個對象的模式.在Java中,每次使用new
關鍵字, 就會產生一個新的對象. 有時我們需要只有一個對象產生, 比如一些管理類, 全局管理其它模塊時, 這個管理類適合採用單例模式.
普通的單例模式分爲2種, 懶漢式和餓漢式.懶漢式比較懶, 用到的時候才創建對象, 餓漢式不講理, 你用不用我都創建好放着.
普通單例模式的祕籍:
* 將構造函數定義爲私有private
, 只能在本類中創建, 不能被繼承.
* 通過private
和static
關鍵字定義一個私有並且靜態的本類實例對象, 保證內存中只有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)模式或從屬者模式).是一個非常棒的降低代碼耦合度的方式.
觀察者模式的祕籍:
* 觀察者在發佈者對象上註冊消息偵聽, 加入消息偵聽列表
* 發佈者遍歷消息偵聽列表, 調用觀察者方法處理消息
* 不同的觀察者對象通常繼承同一個觀察者接口, 通過接口方法統一處理
通常用在一對多或者多對多的場景中, 一個對象數據變化了, 需要通知其他對象的場景. 比如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.