不懂使用为学过,说出用途,绘制结构为了解,不会灵活使用基本等于没学。
前言
有的笔记本工作电压是20V,而中国家庭用电的电压是220V,如何让20V的笔记本在220V的电压下工作,答案就是进入一个电源适配器,这样才能兼容,在软件开发中也有这种不兼容的情况,这时候也可以像电源适配器的方法一样来使用一个扮演着适配器角色的类来协调这些不兼容的结构,这就是适配器模式
什么是适配器模式 Adapter Pattern
将一个接口转换成客户所希望的另一个接口,使接口不兼容的那些类也可以一起工作,其有个别名叫做包装类,适配器模式既可以作为类结构性模式,也可以作为对象结构性模式
(初学者可以参考SSM框架中的service层作为参考,适配器模式屏蔽了底层代码的实现,service层也一样)
注:适配器模式中定义的接口是广义上的接口,可以表示一个方法或者一个方法对的集合
适配器模式的优点
(1)、将目标类和适配者类解耦,通过引入一个适配器来重用现有的适配者类,无须修改原有结构,只需增加一个适配器
(2)、增加了类的透明性和复用性,将具体的业务实现过程封装在适配类中,对于客户端而言是透明的,而且提高了适配类的复用性,同一个适配类可以在不同的系统中复用。
(3)、灵活性和扩展性都非常的好,通过使用配置文件,可以很方便的切换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合开闭原则。
(4)、对于对象适配器而言,可以用一个对象适配器将不同的适配者适配到同一个目标
适配器模式的缺点
(1)、由于JAVA,C#语言的限制,不支持多重继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。
(2)、适配者不能是最终类,如Java中的final类,C#中的sealed类。
(3)、在Java C#这些语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。
适配器模式适用的场景
(1)、系统需要使用一些现有的类,而这些类的接口(例如方法名)不符合系统的需要,甚至没有这些类的源代码
(2)、想创建一些可以重复工作的类,用于与一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作
(3)、适配器模式多用于在程序设计之后或者新增功能的时候,是一种补救的结构性模式
适配器模式的具体实现(对象适配器模式)
目录结构(使用的开发工具是IDEA)
适配器接口以及实现子类
package com.company;
public interface ScoreOperation {
public int[] sort(int array[]); //成绩排序
public int search(int array[],int key); //成绩查找
}
package com.company;
public class OperatonAdapter implements ScoreOperation { //操作适配器:适配器
//定义适配器对象QuickSort对象
private QuickSort quickSort;
//定义适配器对象BinarySearch对象
private BinarySearch binarySearch;
public OperatonAdapter(){
quickSort=new QuickSort();
binarySearch=new BinarySearch();
}
@Override
public int[] sort(int[] array) {
//调用适配者类QuickSort的排序方法
return quickSort.quickSort(array);
}
@Override
public int search(int[] array, int key) {
//调用适配者类binarySearch的查询方法
return binarySearch.binarySearch(array,key);
}
}
适配者类
public class QuickSort {
public int[] quickSort(int array[]){
sort(array,0,array.length-1);
return array;
}
public void sort(int a[],int p, int r){
int x=a[r];
int j=p-1;
for(int i=p;i<=r-1;i++){
if(a[i]<=x){
j++;
swap(a,j,i);
}
}
}
public void swap(int[]a,int i,int j){
int t=a[i];
a[i]=a[j];
a[j]=t;
}
}
public class BinarySearch {
public int binarySearch(int array[],int key){
int low=0;
int high=array.length-1;
while(low<=high){
int mid=(low+high)/2;
int midVal=array[mid];
if(midVal<key){
low=mid+1;
}else if(midVal>key){
high=mid-1;
}
else{
return 1; //找到元素返回一
}
}
return -1; //未找到返回-1;
}
}
辅助工具类
package com.company;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class XMLUtil {
//该类从配置文件中提取一个具体类的类名,并返回一个实例对象
public static Object getBean(){
try {
//创建文档对象
DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
Document document=documentBuilder.parse(
new File(XMLUtil.class.getClassLoader().getResource("").getPath()+"config.xml"));
//获取包含类名的文本节点
NodeList nodeList=document.getElementsByTagName("className");
Node node=nodeList.item(0).getFirstChild();
String name=node.getNodeValue();
//通过类名生成实例对象并将其返回
/*System.out.println(name);*/
Class c=Class.forName(name);
Object obj=c.newInstance();
return obj;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<className>com.company.OperatonAdapter</className>
</config>
客户端测试类
package com.company;
public class Client {
public static void main(String[] args) {
ScoreOperation operation; //针对抽象目标接口编程
operation=(ScoreOperation) XMLUtil.getBean(); //读取配置文件,反射生成对象
int sroces[]={45,56,6,7,45,6}; //定义成绩数组
int result[];
int score;
System.out.println("成绩排序结果:");
result=operation.sort(sroces);
//遍历输出成绩
for (int i:result){
System.out.println(i);
}
System.out.println();
System.out.println("查找成绩56");
score=operation.search(sroces,56);
if(score!=-1){
System.out.println("找到成绩56");
}else{
System.out.println("没有找到成绩56");
}
System.out.println("查找成绩77");
score=operation.search(sroces,77);
if(score!=-1){
System.out.println("找到成绩77");
}else{
System.out.println("没有找到成绩77");
}
}
}
转载请注明出处,掌声送给社会人