设计模式学习--适配器模式(Adapter Pattern)+外观模式(Facade Pattern)

时间:2021-06-06 22:01:17

设计模式学习--适配器模式(Adapter Pattern)+外观模式(Facade Pattern)

2013年6月21日设计模式学习
今天要学习两个设计模式:适配器模式、外观模式
还是老方式,回顾以往的知识

面向对象基础

  • 抽象
  • 封装
  • 多态
  • 继承

面向对象原则

  • 封装变化
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 为交互对象之间的松耦合设计而努力
  • 类应该对扩展开发,对修改关闭
  • 依赖抽象,不要依赖具体类
  • 只和朋友交谈(用来维护设计中的低层解耦)

适配器模式定义

将一个类的接口,转换成客户期望另一个接口。适配器让原本不兼容的类可以合作无间。

外观模式定义

提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

到目前为止我们学习的模式

  • 策略模式
  • 观察者模式
  • 装饰者模式
  • 工厂模式
  • 单件模式
  • 命令模式

关于模式的学习

小巫并不打算一口吃一个胖子,不认为一次就能学好设计模式,要做到灵活运用还是需要沉淀的,程序设计是一门艺术,对我来说是这样,我会一直不停的学习,让自己成为真正的高手。

关于适配器模式

3个对象要清楚:
  • 客户 (客户只看到目标接口)
  • 适配器 (适配器实现目标接口)
  • 被适配者 (所有的请求都委托给被适配器,与适配器组合)

再近一点:用火鸡来冒充鸭子

目标接口
package ducks;
/**
*
* @author wwj
* 适配器模式:鸭接口
*/
public interface Duck {
public void quack();//呱呱叫
public void fly();//飞行
}

目标接口具体实现类
package ducks;

/**
*
*@author wwj
*适配器模式:绿头鸭实现类
*
*/
public class MallardDuck implements Duck {

@Override
public void quack() {
System.out.println("Quack");
}

@Override
public void fly() {
System.out.println("I'm flying");
}

}



被适配对象接口
package ducks;

/**
*
* @author wwj
* 火鸡
*/
public interface Turkey {
public void gobble();//咯咯叫
public void fly();//火鸡也会飞,但飞不远
}

被适配对象接口具体实现类
package ducks;


/**
*
* @author wwj
* 火鸡具体实现类
*/
public class WildTurkey implements Turkey {

@Override
public void gobble() {
System.out.println("Gobble gobble");
}

@Override
public void fly() {
System.out.println("I'm flying a short distance");
}

}

适配器
package ducks;
/**
*
* @author wwj
* 适配器类:用火鸡来冒充鸭子
*/
public class TurkeyAdapter implements Duck {
Turkey turkey;//声明你需要适配的引用对象

/**
* 取得需要适配的对象引用,这里通过构造器来取得这个引用
* @param turkey
*/
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}

@Override
public void quack() { //实现接口中的方法
turkey.gobble();//用适配对象来转换需要实现的功能
}

@Override
public void fly() {
for(int i = 0; i < 5; i++) {
turkey.fly();
}
}

}




测试一下
package ducks;

public class TurkeyTestDrive {
public static void main(String[] args) {
WildTurkey turkey = new WildTurkey(); //创建一只火鸡


MallardDuck duck = new MallardDuck();//创建一只鸭子

Turkey duckAdpter = new DuckAdapter(duck);//传进一个鸭子去,用来假装为火鸡

//测试鸭子
System.out.println("The Duck says...");
duck.quack();
duck.fly();


//测试火鸡
System.out.println("\nThe Turkey says...");
testTurkey(turkey);

//测试适配器
System.out.println("\nThe duckAdapter says...");
testTurkey(turkey);
}

private static void testTurkey(Turkey turkey) {
turkey.gobble();
turkey.fly();
}

}

适配器模式测试结果
The Turkey says...
Gobble gobble
I'm flying a short distance


The Duck says...
Quack
I'm flying


The TurkeyAdapter says...
Gobble gobble
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance


好了,以上就是适配器模式的使用,下面是外观模式

关于外观模式

我们需要明白这个模式的意图是什么:简化接口,把复杂的子系统封装起来,可以使用户更加方便使用功能

一个外观模式的例子:家庭电影观赏

构造家庭影院外观
package hometheater;

public class HomeTheaterFacade {
//这就是组合,我们会用到的子系统组件全部都在这里
Amplifier amp;
Tuner tuner;
DvdPlayer dvd;
CdPlayer cd;
Projector projector;
TheaterLights lights;
Screen screen;
PopcornPopper popper;

/**
* 外观将子系统每一个组件的引用都传入它的构造器中。然后外观把它们赋值给相应的实例变量
* @param amp
* @param tuner
* @param dvd
* @param cd
* @param projector
* @param lights
* @param screen
* @param popper
*/
public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd,
CdPlayer cd, Projector projector, TheaterLights lights,
Screen screen, PopcornPopper popper) {
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.projector = projector;
this.lights = lights;
this.screen = screen;
this.popper = popper;
}

/**
* 实现简化的接口
* @param movie
*/
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();
}

}


各个子系统类的实现
package hometheater;

public class Amplifier {
String description;
Tuner tuner;
DvdPlayer dvd;
CdPlayer cd;

public Amplifier(String description) {
this.description = description;
}

public void on() {
System.out.println(description + " on");
}

public void off() {
System.out.println(description + " off");
}

public void setStereoSound() {
System.out.println(description + " stereo mode on");
}

public void setSurroundSound() {
System.out.println(description + " surround sound on (5 speakers, 1 subwoofer)");
}

public void setVolume(int level) {
System.out.println(description + " setting volume to " + level);
}

public void setTuner(Tuner tuner) {
System.out.println(description + " setting tuner to " + dvd);
this.tuner = tuner;
}

public void setDvd(DvdPlayer dvd) {
System.out.println(description + " setting DVD player to " + dvd);
this.dvd = dvd;
}

public void setCd(CdPlayer cd) {
System.out.println(description + " setting CD player to " + cd);
this.cd = cd;
}

public String toString() {
return description;
}
}

package hometheater;

public class CdPlayer {
String description;
int currentTrack;
Amplifier amplifier;
String title;

public CdPlayer(String description, Amplifier amplifier) {
this.description = description;
this.amplifier = amplifier;
}

public void on() {
System.out.println(description + " on");
}

public void off() {
System.out.println(description + " off");
}

public void eject() {
title = null;
System.out.println(description + " eject");
}

public void play(String title) {
this.title = title;
currentTrack = 0;
System.out.println(description + " playing \"" + title + "\"");
}

public void play(int track) {
if (title == null) {
System.out.println(description + " can't play track "
+ currentTrack + ", no cd inserted");
} else {
currentTrack = track;
System.out.println(description + " playing track " + currentTrack);
}
}

public void stop() {
currentTrack = 0;
System.out.println(description + " stopped");
}

public void pause() {
System.out.println(description + " paused \"" + title + "\"");
}

public String toString() {
return description;
}
}

package hometheater;

public class DvdPlayer {
String description;
int currentTrack;
Amplifier amplifier;
String movie;

public DvdPlayer(String description, Amplifier amplifier) {
this.description = description;
this.amplifier = amplifier;
}

public void on() {
System.out.println(description + " on");
}

public void off() {
System.out.println(description + " off");
}

public void eject() {
movie = null;
System.out.println(description + " eject");
}

public void play(String movie) {
this.movie = movie;
currentTrack = 0;
System.out.println(description + " playing \"" + movie + "\"");
}

public void play(int track) {
if (movie == null) {
System.out.println(description + " can't play track " + track + " no dvd inserted");
} else {
currentTrack = track;
System.out.println(description + " playing track " + currentTrack + " of \"" + movie + "\"");
}
}

public void stop() {
currentTrack = 0;
System.out.println(description + " stopped \"" + movie + "\"");
}

public void pause() {
System.out.println(description + " paused \"" + movie + "\"");
}

public void setTwoChannelAudio() {
System.out.println(description + " set two channel audio");
}

public void setSurroundAudio() {
System.out.println(description + " set surround audio");
}

public String toString() {
return description;
}
}

package hometheater;

public class PopcornPopper {
String description;

public PopcornPopper(String description) {
this.description = description;
}

public void on() {
System.out.println(description + " on");
}

public void off() {
System.out.println(description + " off");
}

public void pop() {
System.out.println(description + " popping popcorn!");
}

public String toString() {
return description;
}
}

package hometheater;

public class Projector {
String description;
DvdPlayer dvdPlayer;

public Projector(String description, DvdPlayer dvdPlayer) {
this.description = description;
this.dvdPlayer = dvdPlayer;
}

public void on() {
System.out.println(description + " on");
}

public void off() {
System.out.println(description + " off");
}

public void wideScreenMode() {
System.out.println(description + " in widescreen mode (16x9 aspect ratio)");
}

public void tvMode() {
System.out.println(description + " in tv mode (4x3 aspect ratio)");
}

public String toString() {
return description;
}
}

package hometheater;

public class Screen {
String description;

public Screen(String description) {
this.description = description;
}

public void up() {
System.out.println(description + " going up");
}

public void down() {
System.out.println(description + " going down");
}


public String toString() {
return description;
}
}


package hometheater;

public class TheaterLights {
String description;

public TheaterLights(String description) {
this.description = description;
}

public void on() {
System.out.println(description + " on");
}

public void off() {
System.out.println(description + " off");
}

public void dim(int level) {
System.out.println(description + " dimming to " + level + "%");
}

public String toString() {
return description;
}
}

package hometheater;

public class Tuner {
String description;
Amplifier amplifier;
double frequency;

public Tuner(String description, Amplifier amplifier) {
this.description = description;
}

public void on() {
System.out.println(description + " on");
}

public void off() {
System.out.println(description + " off");
}

public void setFrequency(double frequency) {
System.out.println(description + " setting frequency to " + frequency);
this.frequency = frequency;
}

public void setAm() {
System.out.println(description + " setting AM mode");
}

public void setFm() {
System.out.println(description + " setting FM mode");
}

public String toString() {
return description;
}
}

可以观赏电影啦
package hometheater;

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, lights, screen, popper);
homeTheater.watchMovie("Raiders of the Lost Ark");
homeTheater.endMovie();
}
}

测试效果:
Get ready to watch a movie...
Popcorn Popper on
Popcorn Popper popping popcorn!
Theater Ceiling Lights dimming to 10%
Theater Screen going down
Top-O-Line Projector on
Top-O-Line Projector in widescreen mode (16x9 aspect ratio)
Top-O-Line Amplifier on
Top-O-Line Amplifier setting DVD player to Top-O-Line DVD Player
Top-O-Line Amplifier surround sound on (5 speakers, 1 subwoofer)
Top-O-Line Amplifier setting volume to 5
Top-O-Line DVD Player on
Top-O-Line DVD Player playing "Raiders of the Lost Ark"
Shutting movie theater down...
Popcorn Popper off
Theater Ceiling Lights on
Theater Screen going up
Top-O-Line Projector off
Top-O-Line Amplifier off
Top-O-Line DVD Player stopped "Raiders of the Lost Ark"
Top-O-Line DVD Player eject
Top-O-Line DVD Player off


好,关于适配器模式和外观模式就记录到这里,接下来会继续学习新的设计模式:模板方法模式。