9.
OO原則:最少知識原則——只和你的密友談話
(即只調用屬於以下範圍的方法:
①該對象本身
②被當作方法的參數而傳遞進來的對象
③此方法索創建或實例化的任何對象
④對象的任何組件)
OO模式:外觀模式——提供一個統一的接口,用來訪問子系統中的一羣接口。外觀定義了一個高層接口,讓子系統更容易使用。
例子:觀看家庭影院的準備和看完後關閉設備等工作。
public class HomeTheaterFacade {
Amplifier amp;
Tuner tuner;
DvdPlayer dvd;
CdPlayer cd;
Projector projector;
TheaterLights lights;
Screen screen;
PopcornPopper popper;
public HomeTheaterFacade(Amplifier amp,
Tuner tuner,
DvdPlayer dvd,
CdPlayer cd,
Projector projector,
Screen screen,
TheaterLights lights,
PopcornPopper popper) {
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.projector = projector;
this.screen = screen;
this.lights = lights;
this.popper = popper;
}
public void watchMovie(String movie) {
System.out.println("Get ready to watch a movie...");
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}
public void endMovie() {
System.out.println("Shutting movie theater down...");
popper.off();
lights.on();
screen.up();
projector.off();
amp.off();
dvd.stop();
dvd.eject();
dvd.off();
}
public void listenToCd(String cdTitle) {
System.out.println("Get ready for an audiopile experence...");
lights.on();
amp.on();
amp.setVolume(5);
amp.setCd(cd);
amp.setStereoSound();
cd.on();
cd.play(cdTitle);
}
public void endCd() {
System.out.println("Shutting down CD...");
amp.off();
amp.setCd(cd);
cd.eject();
cd.off();
}
public void listenToRadio(double frequency) {
System.out.println("Tuning in the airwaves...");
tuner.on();
tuner.setFrequency(frequency);
amp.on();
amp.setVolume(5);
amp.setTuner(tuner);
}
public void endRadio() {
System.out.println("Shutting down the tuner...");
tuner.off();
amp.off();
}
}
public class HomeTheaterTestDrive { public static void main(String[] args) { Amplifier amp = new Amplifier("Top-O-Line Amplifier"); Tuner tuner = new Tuner("Top-O-Line AM/FM Tuner", amp); DvdPlayer dvd = new DvdPlayer("Top-O-Line DVD Player", amp); CdPlayer cd = new CdPlayer("Top-O-Line CD Player", amp); Projector projector = new Projector("Top-O-Line Projector", dvd); TheaterLights lights = new TheaterLights("Theater Ceiling Lights"); Screen screen = new Screen("Theater Screen"); PopcornPopper popper = new PopcornPopper("Popcorn Popper"); HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper); homeTheater.watchMovie("Raiders of the Lost Ark"); homeTheater.endMovie(); } }
HomeTheaterFacade類中的watchMovie()和endMovie()方法等將每項子任務依次處理,對外表現只爲執行一個操作,相當於你按下一個按鈕,就可以開始看電影等操作。
以下是上述類的關係圖:
看到這裏,你應該會覺得,是否可以認爲適配器模式和外觀模式的區別在於:適配器包裝一個類,而外觀模式可以代表許多類?
這樣是不對的!適配器模式將一個或多個類接口變成客戶所期望的一個接口,我們可以適配許多類來提供一個接口讓客戶編碼。
類似的,一個外觀也可以只針對一個擁有複雜接口的類提供簡化的接口。兩種模式的差異,不在於它們“包裝”了幾個類,而是在於它們包裝的意圖。
適配器模式的意圖是,“改變”接口轉換成不同的接口來符合客戶的期望;
而外觀模式的意圖是,提供子系統一個簡化接口,並將客戶從組件的子系統中解耦;
另外,裝飾者模式的意圖是,不改變接口,但加入責任。