天天看點

外觀模式 外觀模式

外觀模式

标簽 : Java與設計模式

外觀模式: 又稱門面模式: 外觀Facade為子系統的一組接口提供一個一緻界面,使得這組子系統易于使用(通過引入一個新的外觀角色降低原系統複雜度,同時降低客戶類與子系統的耦合度).
外觀模式 外觀模式
圖檔來源: 設計模式: 可複用面向對象軟體的基礎.

實作

案例需求: 租房
           

有過自己找房租房經曆的同學能夠體會得到找房是件很痛苦的事, 不光要挨個小區跑而且還要跟(二)房東讨價還價. 于是後來學聰明了, 不再自己挨門挨戶的磨嘴皮子, 而是直接找像鍊家、我愛我家這樣的房屋中介, 他們手上握有一定的房源, 我們隻需付給他們一筆傭金, 他們便可以代我們跟房東講價, 而且他們大都很專業, 省時間又省錢. 此時房屋中介就是一個外觀Facade, 而房屋的出租戶就是子系統SubSystem:

外觀模式 外觀模式
  • Facade
    外觀類: 知道哪些子系統負責處理請求, 将客戶的請求代理給适當的子系統對象:
public class MediumFacade {

    private CuiYuanApartment cuiyuan;

    private XiXiApartment xixi;

    private XiHuApartment xihu;

    public MediumFacade() {
        cuiyuan = new CuiYuanApartment("翠苑小區", , );
        xixi = new XiXiApartment("西溪花園", , );
        xihu = new XiHuApartment("西湖小區", , );
    }

    public void rentingHouse(double price) {
        // 價錢合适而且有房可組
        if (price >= cuiyuan.getPrice() && cuiyuan.getStatus() != ) {
            System.out.println("預訂" + cuiyuan.getLocation());
            cuiyuan.setStatus();
        } else if (price >= xixi.getPrice() && xixi.getStatus() != ) {
            System.out.println("預訂" + xixi.getLocation());
            xixi.setStatus();
        } else if (price >= xihu.getPrice() && xihu.getStatus() != ) {
            System.out.println("預訂" + xihu.getLocation());
            xihu.setStatus();
        } else {
            System.out.println("出價太低/沒有房源 ...");
        }
    }
}
           
  • SubSystem
    子系統集合: 實作子系統功能, 處理 Facade對象指派的任務(注意子系統内沒有任何 Facade資訊,即沒有任何 Facade對象引用):
/**
 * @author jifang
 * @since 16/8/23 上午10:12.
 */
public class XiHuApartment {

    private String location;

    private double price;

    private int status;

    public XiHuApartment(String location, double price, int status) {
        this.location = location;
        this.price = price;
        this.status = status;
    }

    public String getLocation() {
        return location;
    }

    public double getPrice() {
        return price;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }
}

class XiXiApartment {
    private String location;

    private double price;

    private int status;

    public XiXiApartment(String location, double price, int status) {
        this.location = location;
        this.price = price;
        this.status = status;
    }

    public String getLocation() {
        return location;
    }

    public double getPrice() {
        return price;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }
}

class CuiYuanApartment {

    private String location;

    private double price;

    private int status;

    public CuiYuanApartment(String location, double price, int status) {
        this.location = location;
        this.price = price;
        this.status = status;
    }

    public String getLocation() {
        return location;
    }

    public double getPrice() {
        return price;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }
}
           
  • Client

    這樣, Client隻需跟一個房屋中介聯系并給出我們的報價, 他們便會幫我們聯系所有符合的房東:

public class Client {

    @Test
    public void client() {
        MediumFacade facade = new MediumFacade();
        facade.rentingHouse();
    }
}
           

小結

有過面向對象開發經驗的同學 即使沒有聽說過外觀模式, 也完全有可能使用過他, 因為他完美的展現了依賴倒轉原則和迪米特法則的思想, 是非常常用的模式之一.
  • 使用
    外觀模式 外觀模式
    • 首先 在設計初期, 應該有意識的進行層次分離, 比如經典的三層架構, 層與層之間建立Facade, 這樣可以為複雜的子系統提供一個簡單的接口, 使耦合度大大降低.
    • 其次 在開發階段, 子系統往往因為不斷的重構而變得越來越複雜, 增加Facade可以提供一個簡單的接口, 減少子產品間依賴.
    • 第三 在維護一個遺留系統時, 可能這個系統已經非常難以維護和擴充了, 但因為它包含非常重要的功能, 新的需求必須依賴它, 此時可以為新系統開發一個Facade, 為設計粗糙或高複雜度的遺留代碼提供一個的比較清晰簡單的接口, 讓新系統與Facade互動, 而Facade與遺留代碼互動所有繁雜的工作.

繼續閱讀