在Java中实现类适配器模式

时间:2011-06-10 11:35:32

标签: java class design-patterns adapter

在阅读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);
...

这不是类适配器模式吗?

5 个答案:

答案 0 :(得分:11)

在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();
    }
}

现在,您可以将Turkey传递给期望Duck通过TurkeyAdapter的方法。

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

通过使用适配器模式,DuckCatcher现在也可以捕获Turkey(Adapter)Duck

答案 1 :(得分:5)

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

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

答案 2 :(得分:5)

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

答案 3 :(得分:3)

GoF(Gang of Four)告诉我们两种主要的适配器:

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

B中。对象适配器。它们取决于物体成分。

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

interface IntegerValue 
{
    public int getInteger();
}

class IntegerValue implements IntegerValue
{
    @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
{
    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

答案 4 :(得分:0)

通过使用单继承,

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

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

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

  public class CheckboxAdapter extends Checkbox
  { 

      public CheckboxAdapter(String n) 
      {
         super(n);
      }

      public boolean isSelected()
      {
         return getState();
      }
  }

现在我们可以处理AWT改编的复选框,就像我们在isSelected方法中标准的Swing复选框一样。

  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中不可能使用True类适配器,如果它们可以从多个类继承,我们想在适配器类中模仿它。

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