java 設計模式:外觀設計模式

1、概念

外觀設計模式的主要目的在於讓外部減少與子系統內部多個模塊的交互,從而讓外部能夠更簡單的使用子系統。他負責把客戶端的請求轉發給子系統內部的各個模塊進行處理。

2、使用場景

  1. 當你要爲一個複雜子系統提供一個簡單接口時
  2. 客戶程序與抽象類的實現部分之間存在很大的依賴性。引入外觀類可以將子系統與客戶端解耦,從而提高子系統的獨立性和可移植性。
  3. 當你需要構建一個層次結構的子系統時; 在層次化結構中,可以使用外觀模式定義系統中每一層的入口,層與層之間不直接產生聯繫,而通過外觀類建立聯繫,降低層之間的耦合度。

3、UML結構圖分析

4、實際代碼分析


/**
 * 模塊A
 */
public class SubSystemA {

    public void testFunA(){
        System.out.println("testFunA");
    }

}
/**
 * 模塊B
 */
public class SubSystemB {
    public void testFunB(){
        System.out.println("testFunB");
    }
}
/**
 * 模塊C
 */
public class SubSystemC {
    public void testFunC(){
        System.out.println("testFunC");
    }
}
/**
 * Facade 
 */
public class Facade {

    private SubSystemA subSystemA;
    private SubSystemB subSystemB;
    private SubSystemC subSystemC;
    private Facade(){
        subSystemA = new SubSystemA();
        subSystemB = new SubSystemB();
        subSystemC = new SubSystemC();
    }

    private static Facade instance;

    public static Facade getInstance(){
        if(instance==null){
            instance = new Facade();
        }
        return instance;
    }

    public void tastOperation(){
        subSystemA.testFunA();
        subSystemB.testFunB();
        subSystemC.testFunC();
    }
}

//運行
        Facade.getInstance().tastOperation();

由於外觀類維持了對多個子系統類的引用,外觀對象在系統運行時將佔用較多的系統資源,因此需要對外觀對象的數量進行限制,避免系統資源的浪費。可以結合單例模式對外觀類進行改進,將外觀類設計爲一個單例類。通過對外觀模式單例化,可以確保系統中只有唯一一個訪問子系統的入口,降低系統資源的消耗。

我在項目中的實踐:

在項目中經常會出現,網絡請求,緩存本地,本地有緩存用本地緩存,而且網絡請求經常會在多個地方調用,如果不採用外觀模式設計,則會出現客戶端的代碼異常複雜,而且不利於維護。於是我就進行了如下改變,建立中間倉庫類來進行數據切換,客戶端只需要進行對倉庫數據進行調用,不用關心倉庫裏數據怎樣生成的。

/**
 * 建立倉庫接口類
 * TestApiDataSource
 */
public interface TestApiDataSource {


    /**
     * 登陸接口
     * @param params
     * @return
     */
    Observable<GetLoginResponse> getLogin(GetLoginParams params);
}
/**
 * 建立本地數據源(主要是爲了方便客戶端調用)
 * TestApiLocalDataSource
 */
public class TestApiLocalDataSource extends BaseLocalDataSource implements TestApiDataSource {

    
    @Override
    public Observable<GetLoginResponse> getLogin(GetLoginParams params) {

        Observable<GetLoginResponse> observable = Observable.create(new ObservableOnSubscribe<GetLoginResponse>() {
            @Override
            public void subscribe(ObservableEmitter<GetLoginResponse> subscriber)  throws Exception {
                subscriber.onComplete();

            }
        });
        return observable;
    }

}

/**
 * 建立網絡數據源
 * TestApiRemoteDataSource
 */
public class TestApiRemoteDataSource extends BaseRemoteDataSource implements TestApiDataSource {

    /**
     *
     * 請求網絡
     * @param params
     * @return
     */
    @Override
    public Observable<GetLoginResponse> getLogin(GetLoginParams params) {
        return ApiSource.getApiService(AppHuanJingFactory.getAppModel().getApi()).getApi2Service().getLogin(params);
    }

}

/**
 * 建立單例倉庫類
 * TestApiRepository
 */
public class TestApiRepository extends BaseRepository<TestApiLocalDataSource,TestApiRemoteDataSource> implements TestApiDataSource {

    public static volatile TestApiRepository instance;


    public static TestApiRepository getInstance(){
        if(instance==null){
            synchronized (TestApiRepository.class){
                if(instance==null){
                    instance = new TestApiRepository(new TestApiLocalDataSource(),new TestApiRemoteDataSource());
                }
            }
        }
        return instance;
    }

    protected TestApiRepository(TestApiLocalDataSource localDataSource, TestApiRemoteDataSource remoteDataSource) {
        super(localDataSource, remoteDataSource);
    }


    /**
     * 數據源切換
     * #getLogin#
     * @param params
     * @return
     */
    @Override
    public Observable<GetLoginResponse> getLogin(GetLoginParams params) {
        Observable<GetLoginResponse> observable = Observable.
                concat(localDataSource.getLogin(params),
                        remoteDataSource.getLogin(params).
                                doOnNext(new Consumer<GetLoginResponse>() {
                                    @Override
                                    public void accept(GetLoginResponse response) throws Exception {
                                        /**
                                         * cache
                                         */
                                    }
                                })).compose(RxTransformerHelper.<GetLoginResponse>ioToUI()).firstOrError().toObservable();
        return observable;
    }


}
//客戶端執行,不需要考慮具體實現
TestApiRepository.getInstance().getLogin(new GetLoginParams()).subscribe(new BaseRxNetworkResponseObserver<GetLoginResponse>() {
            @Override
            public void onResponse(GetLoginResponse getLoginResponse) {

            }

            @Override
            public void onResponseFail(Exception e) {

            }

            @Override
            protected void onBeforeResponseOperation() {

            }

            @Override
            public void onSubscribe(Disposable d) {
                add(d);
            }
        });

 

優點:

  1. 由於Facade類封裝了各個模塊交互過程,如果今後內部模塊調用關係發生了變化,只需要修改facade實現就可以了
  2. facade實現是可以被多個客戶端調用的
  3. 使得客戶端和子系統之間解耦,讓子系統內部的模塊功能更容易擴展和維護;客戶端根本不需要知道子系統內部的實現,或者根本不需要知道子系統內部的構成,它只需要跟Facade類交互即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章