chapter07_随遇而安——适配器模式和外观模式

  • (1) 适配器的作用

    将一个接口转换成另一个接口

    (2) 使用适配器的过程

    1° 客户通过目标接口调用适配器的方法

    2° 适配器使用 被适配者 的接口, 将请求转换成被适配器的一个或多个调用接口

__实现了调用者和被适配者的解耦__

(3) 示例

Duck.java

    public interface Duck {

        void quack();

        void fly();
    }

Turkey.java

    public interface Turkey {

        void gobble();

        void fly();
    }

TurkeyAdapter.java

    public class TurkeyAdapter implements Duck {

        private Turkey turkey;

        public TurkeyAdapter(Turkey turkey) {

            this.turkey = turkey;
        }

        public void quack() {

            turkey.gobble();
        }

        public void fly() {

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

Turkey和Duck是两个不同的接口, TurkeyAdapter构造器注入一个turkey对象, 将Duck的行为映射成内部turkey对象的行为
  • 适配器模式

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

  • 适配器的实际应用例子

    以前的Enumeration接口转换为现在的Iterator接口

      public class EnumerationIterator implements Iterator {
    
          private Enumeration enumeration;
    
          public EnumerationIterator(Enumeration enumeration) {
    
              this.enumeration = enumeration;
          }
    
          public boolean hasNext() {
    
              return enumeration.hasMoreElements();
          }
    
          public Object next() {
      
              return enumeration.nextElement();
          }
    
          public void remove() {
      
              throw new UnsupportedOperationException();
          }
      }
     

    EnumerationIterator内部包含一个Enumeration对象, 将hasNext和next方法委托之;

    由于Enumeration是一个只读接口, 所以调用remove()时抛出UnsupportedOperationException异常

  • 装饰器模式和适配器模式的对比

    装饰器模式不会改变接口, 它的目标是将新的行为添加到类中;

    适配器模式的作用是改变接口类型

  • (1) 外观模式

    实现一个提供更合理的接口的外观类, 从而将一个复杂的子系统变得容易使用

    (2) 外观模式可以理解为

    一个适配器包装多个被适配者

    (3) 示例

    HomeTheaterFacade.java

      public class HomeTheaterFacade {
    
          private Amplifier amp;
          private Tuner tuner;
          private DvdPlayer dvd;
          private CdPlayer cd;
          private Projector projector;
          private TheaterLights lights;
          private Screen screen;
          private 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);
          }
    
          ...
      }
    

    Amplifier, Tuner, DvdPlayer等都是内部的被适配者, watchMovie有着复杂的流程, 需要各个子系统协同操作;

    HomeTheaterFacade提供了统一的接口方法watchMovie(), 使得函数调用更加友好

    (4) 外观模式使得客户实现从任何子系统中解耦

  • 外观模式和适配器模式的区别

    意图不同!!!

    适配器模式的意图是改变接口以迎合客户的需求;

    外观模式的意图是简化接口

  • 外观模式

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

  • (1) 设计原则: 最少知识原则

    减少对象之间的交互, 只留下几个"密友"对象, 不要让太多的类耦合在一起

    (2) 具体操作方针

    在某个对象的方法内, 我们只应该调用属于以下范围的方法:

    1° 对象本身的方法

    2° 被当作输入参数传进来的对象的方法

    3° 方法内部创建的对象的方法

    4° 对象的内部组件的方法

  • 也就是说, 尽量不要在某个方法中出现 
    
        this.inner.getA().getX()
    
    这种链式调用
    
    (3) 完全遵循"最少知识原则"很可能会导致过度封装(为了防止出现(2)中的情况又包装了几个类), 造成复杂度和开发时间的增加, 所以应__在抽象和速度之间折中__

    你可能感兴趣的:(chapter07_随遇而安——适配器模式和外观模式)