【问题标题】:Implementing Class Adapter Pattern in Java在 Java 中实现类适配器模式
【发布时间】:2011-06-10 11:35:31
【问题描述】:

在阅读Head First Design Patterns 中的类适配器模式时,我遇到了这句话:

类适配器...因为你需要多重继承来实现它,这在Java中是不可能的

只是为了实验,我尝试了以下方法:

interface MyNeededInterface{
    public void operationOne(MyNeededInterface other);
    public MyNeededInterface operationTwo();
}

public class ThirdPartyLibraryClass{
    public void thirdPartyOp();
}

假设我创建:

class ThirdPartyWrapper extends ThirdPartyLibraryClass implements MyNeededInterface{

    @Override
    public void operationOne(ThirdPartyWrapper other){
        this.thirdPartyOp();
        dosomeExtra();
    }
    @Override
    public ThirdPartyWrapper operationTwo(){
        int somevalue = doSomeThingElse();
        return new ThirdPartyWrapper(somevalue);
    }
}

在我的代码中,我可以使用:

MyNeededInterface myclass = createThirdPartyWrapper();
myclass.operationOne(someobj);
...

这不是类适配器模式吗?

【问题讨论】:

    标签: java class design-patterns adapter


    【解决方案1】:

    类适配器模式在 Java 中是不可能的,因为您不能扩展多个类。所以你必须使用使用组合而不是继承的适配器模式。

    通过组合的适配器模式示例如下:

    interface Duck
    {
        public void quack();
    }
    
    class BlackDuck implements Duck
    {
       public void quack() { }
    }
    
    class Turkey
    {
        public void gobble() { }
    }
    
    class TurkeyAdapter implements Duck
    {
        private Turkey t;
    
        public TurkeyAdapter(Turkey t)
        {
            this.t = t;
        }
    
        public void quack()
        {
            // A turkey is not a duck but, act like one
            t.gobble();
        }
    }
    

    现在您可以通过TurkeyAdapterTurkey 传递给期望Duck 的方法。

    class DuckCatcher
    {
        public void catch(Duck duck) { }
    }
    

    通过使用适配器模式,DuckCatcher 现在也能够捕获 Turkey(Adapter)s 和 Ducks。

    【讨论】:

    • 这是对象适配器模式。 OP 想要尝试实现类适配器模式。
    • @Vineet:你能扩展一下吗?我不确定两者之间有什么区别?我以为只有一种通用的“适配器模式”。
    • Head First Patterns 这本书讨论了使用继承(而不是组合)来实现类适配器的变体。这在 C++ 中是可能的 - 例如参见 this example
    • @Vineet:啊,我明白了,谢谢你的链接。但是,通过继承的适配器模式在 Java 中是不可能的。
    • 不同意 Class Adapter 是不可能的;看看这个链接en.wikipedia.org/wiki/Adapter_pattern
    【解决方案2】:

    是的,只要你只包装一个适配器,你就可以创建一个带有接口的类适配器。使用多重继承,您可以采用两个或更多适配者并将它们包装到一个接口中。

    【讨论】:

      【解决方案3】:

      完整的故事是:适配器模式在 Java 中是不可能的,因为 Java 不提供 多重继承。 p>

      在他们的图表中,他们显示Adapter子类既是Target 也是Adaptee。您的示例是(接近)对象适配器模式。不同之处在于您在适配器类中实现了 Target,而不仅仅是将目标子类化(在您的示例中为 MyNeededInterface

      【讨论】:

      • 然而它实现了相同的目标(适配适配者)并且显然不是对象适配模式。如果你不能称它为类适配器模式,那你怎么称呼它?
      【解决方案4】:

      GoF(四人组)告诉我们两种主要的适配器:

      A.类适配器。他们通常使用多重继承来使一个接口适应另一个接口。 (但我们必须记住,在 java 中,不支持通过类进行多重继承(这是有充分理由的 :))。我们需要接口来实现多重继承的概念。)

      B.对象适配器。它们取决于对象的组成。

      为了说明这些概念,我将提供一个简单的示例: (来源:Java 设计模式一书)

      interface IIntegerValue 
      {
          public int getInteger();
      }
      
      class IntegerValue implements IIntegerValue
      {
          @Override
          public int getInteger() 
          {
              return 5;
          }
      }
      // Adapter using interface
      class ClassAdapter extends IntegerValue
      {
          //Incrementing by 2
          public int getInteger()
          {
              return 2 + super.getInteger();
          }
      }
      
      // Adapter using composition
      class ObjectAdapter implements IIntegerValue
      {
          private IIntegerValue myInt;
      
          public ObjectAdapter(IIntegerValue myInt)
          {
              this.myInt=myInt;
          }
      
          //Incrementing by 2
          public int getInteger()
          {
              return 2+this.myInt.getInteger();
          }
      }
      
      class ClassAndObjectAdapter
      {
          public static void main(String args[])
          {
              System.out.println("Class and Object Adapter Demo");
              ClassAdapter ca1=new ClassAdapter();
              System.out.println("Class Adapter is returning :"+ca1.getInteger());
              ClassAdapter ca2=new ClassAdapter();
              ObjectAdapter oa=new ObjectAdapter(new IntegerValue());
              System.out.println("Object Adapter is returning :"+oa.getInteger());
          }
      }
      

      控制台输出:

      类和对象适配器演示
      类适配器正在返回:7
      对象适配器正在返回:7

      【讨论】:

        【解决方案5】:

        类适配器在 Java 中通过使用单继承是可能的。 作为来自Design pattern for dummies 的示例,假设我们必须调整 AWT 复选框以与 Swing 复选框一起使用,我们可以为此编写一个类适配器。

        Swing 中用于确定是否选中复选框的 UI 代码是使用 isSelected 方法完成的。但是,AWT 复选框不支持 isSelected(),而是使用 getState()。

        所以我们可以编写一个适配器来包装一个 SWT 复选框并将 getState() 适配为 isSelected()

          public class CheckboxAdapter extends Checkbox
          { 
        
              public CheckboxAdapter(String n) 
              {
                 super(n);
              }
        
              public boolean isSelected()
              {
                 return getState();
              }
          }
        

        现在我们可以像处理标准 Swing 复选框一样处理适用于 AWT 的复选框。

          public void itemStateChanged(ItemEvent e)
          {
              String outString = new String("Selected: ");
        
              for(int loopIndex = 0; loopIndex 
                 <= checks.length - 1; loopIndex++){
                   if(checks[loopIndex].isSelected()) {
                      outString += " checkbox " + loopIndex;
                   }
               }
              text.setText(outString);
           }
        

        编辑:真正的类适配器在 Java 中是不可能的,如果它们是我们可以从多个类继承,我们想在一个适配器类中模仿。

        另请参阅http://www.journaldev.com/1487/adapter-design-pattern-in-java-example-tutorial,了解 Java 中使用类适配器和对象适配器的两个示例,以实现相同的结果。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-24
          • 1970-01-01
          • 2015-10-19
          相关资源
          最近更新 更多