适配器模式(Adapter Pattern)用于将类的接口转换成不同的形式。
问题提出
假设我们要创建一个移动应用程序,它用于给拍的照片或加载的图片应用各种各样的滤镜。
创建类Image。
创建接口Filter,并定义apply方法。
创建VividFilter类,实现Filter接口。
接着,创建类ImageView,它有image属性和apply方法。
然后在main中创建ImageView对象,并应用VividFilter滤镜。
现在,假设有一个第三方滤镜库,它有数十个漂亮的滤镜,我们不想从头编写这些滤镜,我们想重用这些滤镜。
我们来模拟下。
创建包avaFilters,表示第三方滤镜库。再在其下创建类Caramel模拟某个第三方滤镜,它有方法init(),render(Image image)。
我们尝试应用这个Caramel滤镜,将提示错误,因为第三方的Caramel没有实现Filter接口,不被接受。
解决这个问题,就要用到适配器模式(Adapter Pattern)了。
利用适配器模式,我们可以转接类的接口,以适应我们的需要。
解决方案
当前我们的结构是这样的。
我们不能使用Caramel类是因为该类没有实现Filter接口,它是我们从第三方库引入的,我们不能改变它的源代码。
因此,我们先在图中移除VividFilter类,添加一个CamamelFilter类,该类实现了Filter接口。
CaramelFilter类持有caramel对象,我们将要应用滤镜的图像通过CaramelFilter传递给caramel。
这就是适配器模式(Adapter Pattern)。
适配器模式非常有用,当我们要使用一个现有类但该类的接口形式不符合我们的要求时,就可以使用该模式。
在图中,CaramelFilter类充当了适配器角色,而Caramel则是要适配的对象。
代码实现
适配器模式的代码非常简单。
创建类CaramelFilter实现Filter接口,它有一个caramel对象,在apply方法里,调用caramel的方法,这里是init()和render(image)。
在Main里测试结果。
应用滤镜:(new CaramelAdapter(new Caramel()))。
很简单。
我们这里使用了组合的方式,即CamamelAdapter类由caramel对象组成。还可以使用继承方法来实现,我们来看一下。
我们修改CaramelAdapter,它除了实现Filter接口还继承于Caramel类,这样我们可以去掉caramel对象。在Main里,滤镜应用是:(new CaramelAdapter())。
然而,使用继承不如使用组合灵活,因为Java不支持多重继承,一个类只能拥有一个父类。
记住这个原则:优先使用组合而不是继承!
小结
适配器模式(Adapter Pattern)用于将类的接口转换成不同的形式。