在Java中实现类适配器模式

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

类适配器…因为你需要多个inheritance来实现它,这在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中不能使用类适配器模式,因为您无法扩展多个类。 所以你必须使用使用组合而不是inheritance的适配器模式。

通过组合的适配器模式的示例可以在下面找到:

 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 s。

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

前面提到的完整故事是:Java中的适配器模式是不可能的 ,因为Java不提供多重inheritance

在他们的图中,他们显示Adapter类是TargetAdaptee 子类 。 您的示例是(接近)Object适配器模式。 区别在于您在适配器类中实现Target ,而不是仅仅为目标MyNeededInterface子类(在您的示例中为MyNeededInterface

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

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

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

通过使用单inheritance,类适配器在Java中是可行的。 作为假设设计模式的一个例子,假设我们必须调整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类适配器,如果它们可以从多个类inheritance,我们希望在适配器类中模仿它们。

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