zoukankan      html  css  js  c++  java
  • 适配器模式与外观模式

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

    适配器模式有三种实现方式:类适配器、对象适配器、接口适配器。类适配器由多继承实现,所以针对Java就不可能了,而对象适配器由接口(多组合)实现,所以可扩展性也比较高。

    类适配器,以类给到,在Adapter里,就是将src当做类,继承, 
    对象适配器,以对象给到,在Adapter里,将src作为一个对象,持有。 
    接口适配器,以接口给到,在Adapter里,将src作为一个接口,实现

    类适配器:

    对象适配器:

    被适配者接口Duck:

    1 public interface Duck {
    2     public void quack();
    3     public void fly();
    4 }
    View Code

    具体的实现被适配者:

    1 public class MallardDuck implements Duck {
    2     public void quack() {
    3         System.out.println("Quack");
    4     }
    5  
    6     public void fly() {
    7         System.out.println("I'm flying");
    8     }
    9 }
    View Code

    客户看到的目标接口:

    1 public interface Turkey {
    2     public void gobble();
    3     public void fly();
    4 }
    View Code

    适配器组合被适配者,实现目标接口:

     1 public class DuckAdapter implements Turkey {
     2     Duck duck;
     3     Random rand;
     4  
     5     public DuckAdapter(Duck duck) {
     6         this.duck = duck;
     7         rand = new Random();
     8     }
     9     
    10     public void gobble() {
    11         duck.quack();
    12     }
    13   
    14     public void fly() {
    15         if (rand.nextInt(5)  == 0) {
    16              duck.fly();
    17         }
    18     }
    19 }
    View Code

    测试类:

     1 public class TurkeyTestDrive {
     2     public static void main(String[] args) {
     3         MallardDuck duck = new MallardDuck();
     4         Turkey duckAdapter = new DuckAdapter(duck);
     5  
     6         for(int i=0;i<10;i++) {
     7             System.out.println("The DuckAdapter says...");
     8             duckAdapter.gobble();
     9             duckAdapter.fly();
    10         }
    11     }
    12 }
    View Code

    适配器模式的优点

    1)将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。

    2)增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。

    3)灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

    类适配器模式还具有如下优点:

    由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。

    对象适配器模式还具有如下优点:

    一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。

    适配器模式的缺点

    1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。

    2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

    类适配器模式的缺点如下: 对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
    对象适配器模式的缺点如下: 与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
     
     

    适配器模式应用场景

    类适配器与对象适配器的使用场景一致,仅仅是实现手段稍有区别,二者主要用于如下场景:

      (1)想要使用一个已经存在的类,但是它却不符合现有的接口规范,导致无法直接去访问,这时创建一个适配器就能间接去访问这个类中的方法。

      (2)我们有一个类,想将其设计为可重用的类(可被多处访问),我们可以创建适配器来将这个类来适配其他没有提供合适接口的类。

    接口适配器使用场景:

      (1)想要使用接口中的某个或某些方法,但是接口中有太多方法,我们要使用时必须实现接口并实现其中的所有方法,可以使用抽象类来实现接口,并不对方法进行实现(仅置空),然后我们再继承这个抽象类来通过重写想用的方法的方式来实现。这个抽象类就是适配器。

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

    原则:最少知识原则---只和你的密友谈话。

    电影院外观:

     1 public class HomeTheaterFacade {
     2     Amplifier amp;
     3     Tuner tuner;
     4     DvdPlayer dvd;
     5     CdPlayer cd;
     6     TheaterLights lights;
     7     Screen screen;
     8     PopcornPopper popper;
     9  
    10     public HomeTheaterFacade(Amplifier amp, 
    11                  Tuner tuner, 
    12                  DvdPlayer dvd, 
    13                  CdPlayer cd, 
    14                  Screen screen,
    15                  TheaterLights lights,
    16                  PopcornPopper popper) {
    17  
    18         this.amp = amp;
    19         this.tuner = tuner;
    20         this.dvd = dvd;
    21         this.cd = cd;
    22         this.screen = screen;
    23         this.lights = lights;
    24         this.popper = popper;
    25     }
    26  
    27     public void watchMovie(String movie) {
    28         System.out.println("Get ready to watch a movie...");
    29         popper.on();
    30         popper.pop();
    31         lights.dim(10);
    32         screen.down();
    33         amp.on();
    34         amp.setDvd(dvd);
    35         amp.setSurroundSound();
    36         amp.setVolume(5);
    37         dvd.on();
    38         dvd.play(movie);
    39     }
    40  
    41  
    42     public void endMovie() {
    43         System.out.println("Shutting movie theater down...");
    44         popper.off();
    45         lights.on();
    46         screen.up();
    47         amp.off();
    48         dvd.stop();
    49         dvd.eject();
    50         dvd.off();
    51     }
    52 
    53     public void listenToCd(String cdTitle) {
    54         System.out.println("Get ready for an audiopile experence...");
    55         lights.on();
    56         amp.on();
    57         amp.setVolume(5);
    58         amp.setCd(cd);
    59         amp.setStereoSound();
    60         cd.on();
    61         cd.play(cdTitle);
    62     }
    63 
    64     public void endCd() {
    65         System.out.println("Shutting down CD...");
    66         amp.off();
    67         amp.setCd(cd);
    68         cd.eject();
    69         cd.off();
    70     }
    71 
    72     public void listenToRadio(double frequency) {
    73         System.out.println("Tuning in the airwaves...");
    74         tuner.on();
    75         tuner.setFrequency(frequency);
    76         amp.on();
    77         amp.setVolume(5);
    78         amp.setTuner(tuner);
    79     }
    80 
    81     public void endRadio() {
    82         System.out.println("Shutting down the tuner...");
    83         tuner.off();
    84         amp.off();
    85     }
    86 }
    View Code

    测试类:

     1 public class HomeTheaterTestDrive {
     2     public static void main(String[] args) {
     3         Amplifier amp = new Amplifier("Top-O-Line Amplifier");
     4         Tuner tuner = new Tuner("Top-O-Line AM/FM Tuner", amp);
     5         DvdPlayer dvd = new DvdPlayer("Top-O-Line DVD Player", amp);
     6         CdPlayer cd = new CdPlayer("Top-O-Line CD Player", amp);
     7         TheaterLights lights = new TheaterLights("Theater Ceiling Lights");
     8         Screen screen = new Screen("Theater Screen");
     9         PopcornPopper popper = new PopcornPopper("Popcorn Popper");
    10  
    11         HomeTheaterFacade homeTheater = 
    12                 new HomeTheaterFacade(amp, tuner, dvd, cd, 
    13                          screen, lights, popper);
    14  
    15         homeTheater.watchMovie("Raiders of the Lost Ark");
    16         homeTheater.endMovie();
    17     }
    18 }
    View Code

    结果:

  • 相关阅读:
    移动端的头文件
    时间倒计时
    H5 判断应用是否打开或是下载
    创建 XMLHttpRequest 对象
    JS 发送POST
    总结题
    uploadify 插件,去了进度条
    PC 拖动 以百分比计算
    pc 拖动效果,拖动带范围
    spring.net 在demo中的分析
  • 原文地址:https://www.cnblogs.com/cing/p/9168178.html
Copyright © 2011-2022 走看看