设计模式系列--Adapter

一.类图

类适配器:

 

对象适配器:

 

二.意图

将一个类的接口转换成客户希望的另外一个接口。A d a p t e r 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

三.适用性

a) 你想使用一个已经存在的类,而它的接口不符合你的需求。

b) 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。

c) (仅适用于对象A d a p t e r)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

 

四.实例

随着西方文化在中国的盛行,外国的饮食也受到人们的追捧。KFC、麦当劳在中国可谓是遍地开花。但是一些上了年纪的人总是吃不惯哪些汉堡薯条的东西,米饭炒菜对他们来说更有诱惑力。

当然KFC也早就注意到了这样的问题,经过长时间的讨论于是他们提出了这样的解决方案:建立中式的KFC餐馆,聘用中国的厨师为那些来中式KFC的人做饭。

看一下代码实现吧:

package explore.adapter;

public interface WestRestaurant {
public void westernStyleFood();
}

package explore.adapter;

public interface ChineseRestaurant {
public void chineseStyleFood();
}

package explore.adapter;

public class SiChuanRestaurant implements ChineseRestaurant {
@Override
public void chineseStyleFood() {
System.out.println("青椒肉丝盖饭...");

}

}

package explore.adapter;

public class KFC implements WestRestaurant {

@Override
public void westernStyleFood() {
System.out.println("薯条汉堡...");
}

}

package explore.adapter;

public class KFCChineseRestaurant1 implements WestRestaurant {
private ChineseRestaurant cr;

public KFCChineseRestaurant1(ChineseRestaurant cr) {
this.cr = cr;
}

@Override
public void westernStyleFood() {
cr.chineseStyleFood();
}

}

package explore.adapter;

public class KFCChineseRestaurant2 extends SiChuanRestaurant implements WestRestaurant {
@Override
public void westernStyleFood() {
super.chineseStyleFood();
}

}

package explore.adapter;

public class CompositeRestaurant implements WestRestaurant, ChineseRestaurant {
private WestRestaurant wr;
private ChineseRestaurant cr;

public CompositeRestaurant(WestRestaurant wr) {
this.wr = wr;
}

public CompositeRestaurant(ChineseRestaurant cr) {
this.cr = cr;
}

@Override
public void chineseStyleFood() {
wr.westernStyleFood();
}

@Override
public void westernStyleFood() {
cr.chineseStyleFood();
}

}

package explore.adapter;

public class Client {
public static void main(String[] args) {
KFCChineseRestaurant1 kcr1 = new KFCChineseRestaurant1(new SiChuanRestaurant());
kcr1.westernStyleFood();
KFCChineseRestaurant2 kcr2 = new KFCChineseRestaurant2();
kcr2.westernStyleFood();
CompositeRestaurant cr = new CompositeRestaurant(new SiChuanRestaurant());
cr.westernStyleFood();
}
}

适配器的三种实现形式,上面的代码也一一给出,一种是组合的方法就是类适配器,一种是继承的方式就是对象适配器,还有一种双向的适配器。

五.Adapter模式在IO包中的应用

 

public class InputStreamReader extends Reader {

private final StreamDecoder sd;

/**
* Creates an InputStreamReader that uses the default charset.
*
*
@param in An InputStream
*/
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}
... ...

/**
* Reads a single character.
*
*
@return The character read, or -1 if the end of the stream has been
* reached
*
*
@exception IOException If an I/O error occurs
*/
public int read() throws IOException {
return sd.read();
}

 

咦?好多童鞋可能会问:怎么在InputStreamReader中没有发现InputStream的任何身影呢?这点不足为怪。因为我们已经知道:InputStream是按字节流的方式读取文件,而Reader是按照字符流的形式读取文件。所以要实现真正的适配要对字节流和字符流之间进行一个解码。

 

StreamDecoder就是为解决这个问题出现的。StreamDecoder中定义了三个静态工厂方法

 


 

每一个方法都会返回一个StreamDecoder的实例。

 

我们再来看一下read()方法,read()方法直接调用了StreamDecoderread方法。这理解起来就顺其自然了。





posted @ 2012-03-19 16:57  focusJ  阅读(342)  评论(0编辑  收藏  举报