在阅读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);
...
这不是类适配器模式吗?
答案 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
类子类 Target
和Adaptee
。您的示例是(接近)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,以获得相同的结果。