經常使用設計模式

工廠設計模式

  • 工廠設計模式,主要用於進行實例化對象時的解耦操做,避免使用new關鍵字實例化對象,經過反射,根據類名稱動態建立對象
  • 示例:
package design;
/**
   *靜態工廠模式
   */
public class Factory {
/**
   *構造方法私有化
   */
private Factory (){

 }
/**
   * 獲取指定類名稱的對象
   * @param className    * @param <T>
   * @return T
   */
public static <T> T getInstance(String className){
        T object =null;
        try {
            object = (T) Class.forName(className).newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return object;
    }
}

動態代理模式

  • 動態代理模式,主要用於對同一接口子類的相同邏輯進行代理操做
  • 示例:
package design;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
   * 動態代理模式
   */
public class DynamicProxy implements InvocationHandler {
    private Object target;
    /**
     * 代理的目標對象
     * @param target
     * @return
     */
    public Object proxy(Object target){
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    /**
     * 目標方法執行前執行
     * @param object
     */
    public void before(Object object){
        System.out.println("目標方法執行前執行");
    }
    /**
     * 目標方法執行後執行
     * @param object
     */
    public void after(Object object){
        System.out.println("目標方法執行後執行");
    }
    /**
     * Processes a method invocation on a proxy instance and returns
     * the result.  This method will be invoked on an invocation handler
     * when a method is invoked on a proxy instance that it is
     * associated with.
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.before(proxy);
        Object result =method.invoke(proxy,args);
        this.after(result);
        return result;
    }
}

單例模式一

  • 單例模式一:採用static final 修飾在類內部實例化的對象,保證對象的惟一性,此種方式,實在類加載的過程當中實例化對象,不管是否使用,都會實例化。
  • 示例
package design;
/**
   * 單例模式一
   */
public class SingletonOne {
    /**
     * 實例化對象惟一
     */
    private static final SingletonOne INSTANCE =new SingletonOne();
    /**
     * 構造方法私有化
     */
    private SingletonOne(){

    }
    /**
     * 獲取單例對象
     * @return
     */
    public static SingletonOne getInstance(){
        return INSTANCE;
    }
}

單例模式二

  • 單例模式二:採用volatile關鍵字修飾實例化對象,並經過同步鎖(鎖Class)的形式,保證明例化對象的惟一性,此方式在第一次使用時進行實例化
  • volatile關鍵字修飾的變量與普通變量的讀取方式不一樣
01.png
volatile定義的變量,將直接使用原始數據進行處理,更改後當即生效
  • 示例
package design;
/**
   * 單例模式二
   */
public class SingletonTwo {
    /**
     * 使用volatile關鍵字修飾單例對象
     * volatile定義的變量,將直接使用原始數據進行處理,更改後當即生效
     */
    public static volatile SingletonTwo instance;
    /**
     * 構造方法私有化
     */
    private SingletonTwo(){

    }
    /**
     * 獲取單例對象
     * @return
     */
    public static SingletonTwo getInstance(){
        if(instance ==null){
            //經過同步鎖住當前類,來保證線程安全,並提升性能,若直接同步該方法,會大大下降性能
            synchronized (SingletonTwo.class){
                if (instance ==null){
                    instance =new SingletonTwo();
                }
            }
        }
        return instance;
    }
}

單例模式三

  • 單例模式三:基於Jvm類加載機制實現單例
  • 示例
/**
 * 單例模式三
 */
public class ClassSingletonDemo {

    /**
     * 構造方法私有化
     */
    private ClassSingletonDemo(){};

    /**
     * 靜態方法獲取實例
     */
    public static ClassSingletonDemo getInstance(){
        return SingletonHandler.singleton;
    }

    /**
     * 內部靜態類保證只初始化一次
     */
    private static class SingletonHandler {
        private static ClassSingletonDemo singleton = new ClassSingletonDemo();
        static {
            System.out.println("This's innerClass's static code block");
        }
    }
}

單例模式四

  • 單例模式四:基於Enum類型的加載機制實現單例
  • 示例
/**
 * 單例模式四
 */
public class EnumSingletonDemo {

    /**
     * 構造方法私有化
     */
    private EnumSingletonDemo(){}

    /**
     * 靜態方法獲取實例
     */
    public static EnumSingletonDemo getInstance(){
        return Singleton.INSTANCE.getInstance();
    }

    /**
     * 私有枚舉,只被JVM加載一次,只實例化一次
     */
    private enum Singleton{

        INSTANCE;

        private EnumSingletonDemo singleton;

        Singleton(){
            singleton = new EnumSingletonDemo();
        }

        public EnumSingletonDemo getInstance(){
            return singleton;
        }
    }

}

中介者模式

(轉載自喻紅葉《Java與模式-中介者模式》
  • 中介者模式的定義:用一箇中介對象來封裝一些列的對象交互,中介者使得各對象不須要顯式地相互引用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。中介者模式解決問題的思路很簡單,就是經過引入一箇中介對象,讓其餘對象只與中介對象交互,而中介對象知道如何和其餘全部對象的交互,這樣對象之間的交互關係就沒有了,從而實現了對象之間的解耦。由此,咱們也能夠看出一個問題,那就是中介對象控制着整個系統的邏輯,它會過於複雜,這是一個缺點。中介者模式的本質是封裝交互:java

    • (1)對象在自身狀態發生改變時報告給中介對象;
    • (2)中介對象控制着整個系統的邏輯,它知道如何與全部對象交互;
    • (3)對象須要對中介對象發出的請求做出迴應。
  • 中介者模式中的角色:設計模式

    • Mediator:中介者接口,定義各個同事之間交互所須要的方法;
    • ConcreteMediator:具體的中介者,它須要瞭解並維護各個同事對象,並負責具體的協調各同事對象的交互關係;
    • Colleague:全部同事對象的父類,通常實現成抽象類,主要負責約束同事對象的類型,並負責實現一些公共功能;
    • ConcreteMediator:具體的同事類,實現本身的業務,當須要與其餘同事對象通訊時,就與持有的中介者通訊,中介者會負責與其餘同事的交互。在標準的中介者模式中,將使用中介者來交互的那些對象叫作同事類,它們繼承自相同的父類,因此叫作同事。正是因爲它們之間的交互很複雜,因此才產生了把這些交互關係分離出去,讓中介者來處理。
  • 示例:安全

    • 以電腦來看電影爲例子,首先光驅從光盤中讀取數據,而後通知CPU將數據分離成音頻和視頻,CPU處理完畢後再分別將數據傳送給聲卡和顯卡進行播放。從上面的描述的中發現,光驅盒CPU是耦合的,CPU又和聲卡顯卡是耦合的,怎麼解耦的呢?若是使用中介者模式,經過引入主板做爲中介者,全部的對象都與主板交互,那麼播放電影的流程就變成了這樣:ide

      • (1)光驅從光盤讀取到數據,通知主板,數據準備好了;
      • (2)主板收到光驅的請求後,將原始數據傳給CPU,讓它將數據分離成音頻和視頻;
      • (3)CPU將數據分離後,通知主板,數據分離完畢;
      • (4)主板收到CPU通知後,分別將音頻和視頻傳給聲卡和顯卡;
      • (5)聲卡和顯卡同時播放。

這樣一個過程當中,全部的類只與主板耦合,而不與其餘類保持關係,作到了解耦,並且過程很清晰。實際上計算機硬件就是這樣通訊的,只不過更復雜一些,因此這些東西都是相通的,重要的是思想。性能

  • Java實現:this

    • 同事對象的父類
package design;
/**
 * 同事對象的父類,通常實現成抽象類,用於約束同事對象的類型
 * 同時實現一些功能公共方法,例如持有中介者對象
 */
public abstract class Colleague {
    //全部的同事對象都須要持有中介對象
    private Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    public Mediator getMediator() {
        return mediator;
    }
}
  • 中介者接口
package design;
/**
 * 中介者接口
 */
public interface  Mediator {
    /**
     * 同事對象自身狀態改變時,經過這個方法通知中介者對象
     * @param obj
     */
    public void changed(Colleague obj);

    /**
     * 中介者對象須要知道全部同事對象
     * @param instance
     */
    public void setCDDriver(CDDriver instance);
    public void setCPU(CPU instance);
    public void setVideoCard(Video instance);
    public void setSoundCard(Sound instance);
}
  • 光驅類
package design;
/**
 * 光驅類,負責從光盤中讀取數據
 */
class CDDriver extends Colleague {
    //從光盤讀取的原始數據
    private String originData;

    public CDDriver(Mediator mediator) {
        super(mediator);
    }
    public String getOriginData() {
        return originData;
    }

    /**
     * 讀取光盤數據,一旦讀取到數據,就要通知中介者對象數據已經準備好了
     */
    public void readCD(String originData) {
        this.originData = originData;
        //通知中介對象,本身的狀態發生了改變
        getMediator().changed(this);
    }
}
  • CPU類
package design;
/**
 * CPU類,負責將原始數據分離成音頻和視頻
 */
public class CPU extends Colleague {

    //聲音數據
    private String soundData;
    //視頻數據
    private String videoData;

    public CPU(Mediator mediator) {
        super(mediator);
    }
    public String getSoundData() {
        return soundData;
    }
    public String getVideoData() {
        return videoData;
    }

    /**
     * 將數據分離,同時通知中介者對象,數據已經分離
     * @param originData
     */
    public void sperateData(String originData) {
        this.soundData = originData.split(",")[1];
        this.videoData = originData.split(",")[0];

        //通知中介對象,本身的狀態發生了改變
        getMediator().changed(this);
    }
}
  • 顯卡類,播放視頻
package design;
/**
 * 顯卡類,播放視頻
 */
public class Video extends Colleague {

    public Video(Mediator mediator) {
        super(mediator);
    }
    public void showVideo(String videoData) {
        System.out.println("正在觀看:" + videoData);
    }
}
  • 聲卡類
package design;

/**
 * 聲卡類,播放聲音
 */
public class Sound extends Colleague {

    public Sound(Mediator mediator) {
        super(mediator);
    }
    public void showSound(String soundData) {
        System.out.println("解說:" + soundData);
    }
}
  • 主板類
package design;
/**
 * 主板類,實現中介者
 */
public class MainBoard implements Mediator {
    private CDDriver cd;
    private CPU cpu;
    private Video vc;
    private Sound sc;

    public void setCDDriver(CDDriver instance) {
        this.cd = instance;
    }
    public void setCPU(CPU instance) {
        this.cpu = instance;
    }
    public void setVideoCard(Video instance) {
        this.vc = instance;
    }
    public void setSoundCard(Sound instance) {
        this.sc = instance;
    }

    /**
     * 當同時對象自身狀態發生改變時,調用此方法通知中介者對象
     * 中介者對象在進行邏輯控制,與其餘同對象交互
     */
    public void changed(Colleague obj) {
        //若是是光驅類,須要通知CPU去分離數據
        if(obj instanceof CDDriver) {
            String originData = ((CDDriver) obj).getOriginData();
            this.cpu.sperateData(originData);
        }else if(obj instanceof CPU){//若是是CPU類,須要通知聲卡和顯卡去播放
            String videoData = ((CPU) obj).getVideoData();
            String soundData = ((CPU) obj).getSoundData();
            this.vc.showVideo(videoData);
            this.sc.showSound(soundData);
        }
    }
}
  • 客戶端
package design;
/**
 * 客戶端
 */
public class Client {
    public static void main(String[] args) {
        Mediator mediator = new MainBoard();
        CDDriver cd = new CDDriver(mediator);
        CPU cpu = new CPU(mediator);
        Video vc = new Video(mediator);
        Sound sc = new Sound(mediator);
        mediator.setCDDriver(cd);
        mediator.setCPU(cpu);
        mediator.setSoundCard(sc);
        mediator.setVideoCard(vc);
        //光驅讀數據,通知中介者,中介者通知CPU去分離數據,CPU分離數據完成,通知中介者,中介者通知聲卡和顯卡播放
        cd.readCD("終結者,終結者音頻");
    }
}
相關文章
相關標籤/搜索