常用設(shè)計(jì)模式

工廠設(shè)計(jì)模式

  • 工廠設(shè)計(jì)模式,主要用于進(jìn)行實(shí)例化對(duì)象時(shí)的解耦操作,避免使用new關(guān)鍵字實(shí)例化對(duì)象,通過(guò)反射,根據(jù)類名稱動(dòng)態(tài)創(chuàng)建對(duì)象
  • 示例:
package design;
/**
   *靜態(tài)工廠模式
   */
public class Factory {
/**
   *構(gòu)造方法私有化
   */
private Factory (){

 }
/**
   * 獲取指定類名稱的對(duì)象
   * @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;
    }
}

動(dòng)態(tài)代理模式

  • 動(dòng)態(tài)代理模式,主要用于對(duì)同一接口子類的相同邏輯進(jìn)行代理操作
  • 示例:
package design;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
   * 動(dòng)態(tài)代理模式
   */
public class DynamicProxy implements InvocationHandler {
    private Object target;
    /**
     * 代理的目標(biāo)對(duì)象
     * @param target
     * @return
     */
    public Object proxy(Object target){
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    /**
     * 目標(biāo)方法執(zhí)行前執(zhí)行
     * @param object
     */
    public void before(Object object){
        System.out.println("目標(biāo)方法執(zhí)行前執(zhí)行");
    }
    /**
     * 目標(biāo)方法執(zhí)行后執(zhí)行
     * @param object
     */
    public void after(Object object){
        System.out.println("目標(biāo)方法執(zhí)行后執(zhí)行");
    }
    /**
     * 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 修飾在類內(nèi)部實(shí)例化的對(duì)象,保證對(duì)象的唯一性,此種方式,實(shí)在類加載的過(guò)程中實(shí)例化對(duì)象,無(wú)論是否使用,都會(huì)實(shí)例化。
  • 示例
package design;
/**
   * 單例模式一
   */
public class SingletonOne {
    /**
     * 實(shí)例化對(duì)象唯一
     */
    private static final SingletonOne INSTANCE =new SingletonOne();
    /**
     * 構(gòu)造方法私有化
     */
    private SingletonOne(){

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

單例模式二

  • 單例模式二:采用volatile關(guān)鍵字修飾實(shí)例化對(duì)象,并通過(guò)同步鎖(鎖Class)的形式,保證實(shí)例化對(duì)象的唯一性,此方式在第一次使用時(shí)進(jìn)行實(shí)例化
  • volatile關(guān)鍵字修飾的變量與普通變量的讀取方式不同
01.png

volatile定義的變量,將直接使用原始數(shù)據(jù)進(jìn)行處理,更改后立即生效

  • 示例
package design;
/**
   * 單例模式二
   */
public class SingletonTwo {
    /**
     * 使用volatile關(guān)鍵字修飾單例對(duì)象
     * volatile定義的變量,將直接使用原始數(shù)據(jù)進(jìn)行處理,更改后立即生效
     */
    public static volatile SingletonTwo instance;
    /**
     * 構(gòu)造方法私有化
     */
    private SingletonTwo(){

    }
    /**
     * 獲取單例對(duì)象
     * @return
     */
    public static SingletonTwo getInstance(){
        if(instance ==null){
            //通過(guò)同步鎖住當(dāng)前類,來(lái)保證線程安全,并提高性能,若直接同步該方法,會(huì)大大降低性能
            synchronized (SingletonTwo.class){
                if (instance ==null){
                    instance =new SingletonTwo();
                }
            }
        }
        return instance;
    }
}

中介者模式

(轉(zhuǎn)載自喻紅葉《Java與模式-中介者模式》
  • 中介者模式的定義:用一個(gè)中介對(duì)象來(lái)封裝一些列的對(duì)象交互,中介者使得各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。中介者模式解決問(wèn)題的思路很簡(jiǎn)單,就是通過(guò)引入一個(gè)中介對(duì)象,讓其他對(duì)象只與中介對(duì)象交互,而中介對(duì)象知道如何和其他所有對(duì)象的交互,這樣對(duì)象之間的交互關(guān)系就沒(méi)有了,從而實(shí)現(xiàn)了對(duì)象之間的解耦。由此,我們也可以看出一個(gè)問(wèn)題,那就是中介對(duì)象控制著整個(gè)系統(tǒng)的邏輯,它會(huì)過(guò)于復(fù)雜,這是一個(gè)缺點(diǎn)。中介者模式的本質(zhì)是封裝交互:
    • (1)對(duì)象在自身狀態(tài)發(fā)生改變時(shí)報(bào)告給中介對(duì)象;
    • (2)中介對(duì)象控制著整個(gè)系統(tǒng)的邏輯,它知道如何與所有對(duì)象交互;
    • (3)對(duì)象需要對(duì)中介對(duì)象發(fā)出的請(qǐng)求作出回應(yīng)。
  • 中介者模式中的角色:
    • Mediator:中介者接口,定義各個(gè)同事之間交互所需要的方法;
    • ConcreteMediator:具體的中介者,它需要了解并維護(hù)各個(gè)同事對(duì)象,并負(fù)責(zé)具體的協(xié)調(diào)各同事對(duì)象的交互關(guān)系;
    • Colleague:所有同事對(duì)象的父類,一般實(shí)現(xiàn)成抽象類,主要負(fù)責(zé)約束同事對(duì)象的類型,并負(fù)責(zé)實(shí)現(xiàn)一些公共功能;
    • ConcreteMediator:具體的同事類,實(shí)現(xiàn)自己的業(yè)務(wù),當(dāng)需要與其他同事對(duì)象通信時(shí),就與持有的中介者通信,中介者會(huì)負(fù)責(zé)與其他同事的交互。在標(biāo)準(zhǔn)的中介者模式中,將使用中介者來(lái)交互的那些對(duì)象叫做同事類,它們繼承自相同的父類,所以叫做同事。正是由于它們之間的交互很復(fù)雜,所以才產(chǎn)生了把這些交互關(guān)系分離出去,讓中介者來(lái)處理。
  • 示例:
    • 以電腦來(lái)看電影為例子,首先光驅(qū)從光盤(pán)中讀取數(shù)據(jù),然后通知CPU將數(shù)據(jù)分離成音頻和視頻,CPU處理完畢后再分別將數(shù)據(jù)傳送給聲卡和顯卡進(jìn)行播放。從上面的描述的中發(fā)現(xiàn),光驅(qū)盒CPU是耦合的,CPU又和聲卡顯卡是耦合的,怎么解耦的呢?如果使用中介者模式,通過(guò)引入主板作為中介者,所有的對(duì)象都與主板交互,那么播放電影的流程就變成了這樣:
      • (1)光驅(qū)從光盤(pán)讀取到數(shù)據(jù),通知主板,數(shù)據(jù)準(zhǔn)備好了;
      • (2)主板收到光驅(qū)的請(qǐng)求后,將原始數(shù)據(jù)傳給CPU,讓它將數(shù)據(jù)分離成音頻和視頻;
      • (3)CPU將數(shù)據(jù)分離后,通知主板,數(shù)據(jù)分離完畢;
      • (4)主板收到CPU通知后,分別將音頻和視頻傳給聲卡和顯卡;
      • (5)聲卡和顯卡同時(shí)播放。
        這樣一個(gè)過(guò)程中,所有的類只與主板耦合,而不與其他類保持關(guān)系,做到了解耦,而且過(guò)程很清晰。實(shí)際上計(jì)算機(jī)硬件就是這樣通信的,只不過(guò)更復(fù)雜一些,所以這些東西都是相通的,重要的是思想。
  • Java實(shí)現(xiàn):
    • 同事對(duì)象的父類
package design;
/**
 * 同事對(duì)象的父類,一般實(shí)現(xiàn)成抽象類,用于約束同事對(duì)象的類型
 * 同時(shí)實(shí)現(xiàn)一些功能公共方法,例如持有中介者對(duì)象
 */
public abstract class Colleague {
    //所有的同事對(duì)象都需要持有中介對(duì)象
    private Mediator mediator;

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

    public Mediator getMediator() {
        return mediator;
    }
}
  • 中介者接口
package design;
/**
 * 中介者接口
 */
public interface  Mediator {
    /**
     * 同事對(duì)象自身狀態(tài)改變時(shí),通過(guò)這個(gè)方法通知中介者對(duì)象
     * @param obj
     */
    public void changed(Colleague obj);

    /**
     * 中介者對(duì)象需要知道所有同事對(duì)象
     * @param instance
     */
    public void setCDDriver(CDDriver instance);
    public void setCPU(CPU instance);
    public void setVideoCard(Video instance);
    public void setSoundCard(Sound instance);
}
  • 光驅(qū)類
package design;
/**
 * 光驅(qū)類,負(fù)責(zé)從光盤(pán)中讀取數(shù)據(jù)
 */
class CDDriver extends Colleague {
    //從光盤(pán)讀取的原始數(shù)據(jù)
    private String originData;

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

    /**
     * 讀取光盤(pán)數(shù)據(jù),一旦讀取到數(shù)據(jù),就要通知中介者對(duì)象數(shù)據(jù)已經(jīng)準(zhǔn)備好了
     */
    public void readCD(String originData) {
        this.originData = originData;
        //通知中介對(duì)象,自己的狀態(tài)發(fā)生了改變
        getMediator().changed(this);
    }
}
  • CPU類
package design;
/**
 * CPU類,負(fù)責(zé)將原始數(shù)據(jù)分離成音頻和視頻
 */
public class CPU extends Colleague {

    //聲音數(shù)據(jù)
    private String soundData;
    //視頻數(shù)據(jù)
    private String videoData;

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

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

        //通知中介對(duì)象,自己的狀態(tài)發(fā)生了改變
        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("解說(shuō):" + soundData);
    }
}
  • 主板類
package design;
/**
 * 主板類,實(shí)現(xiàn)中介者
 */
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;
    }

    /**
     * 當(dāng)同時(shí)對(duì)象自身狀態(tài)發(fā)生改變時(shí),調(diào)用此方法通知中介者對(duì)象
     * 中介者對(duì)象在進(jìn)行邏輯控制,與其他同對(duì)象交互
     */
    public void changed(Colleague obj) {
        //如果是光驅(qū)類,需要通知CPU去分離數(shù)據(jù)
        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);
        //光驅(qū)讀數(shù)據(jù),通知中介者,中介者通知CPU去分離數(shù)據(jù),CPU分離數(shù)據(jù)完成,通知中介者,中介者通知聲卡和顯卡播放
        cd.readCD("終結(jié)者,終結(jié)者音頻");
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,715評(píng)論 19 139
  • 1 場(chǎng)景問(wèn)題# 1.1 如果沒(méi)有主板## 大家都知道,電腦里面各個(gè)配件之間的交互,主要是通過(guò)主板來(lái)完成的(事實(shí)上主...
    七寸知架構(gòu)閱讀 2,302評(píng)論 0 56
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,871評(píng)論 18 399
  • 設(shè)計(jì)模式是解決特定問(wèn)題的一系列套路。設(shè)計(jì)模式的使用不是語(yǔ)法規(guī)定,不要為了套用設(shè)計(jì)模式而用設(shè)計(jì)模式,它的使用為了解決...
    閑庭閱讀 7,467評(píng)論 2 18
  • 秋燥令人咳 茫茫一片霧 落不下的雀啾 枯了殘荷的筋骨 勾起誰(shuí)難以想象的夢(mèng)境 起了 碎了 終不過(guò)是你 的 一點(diǎn)癡想 ...
    葉抽抽閱讀 236評(píng)論 0 0

友情鏈接更多精彩內(nèi)容