設計模式之適配器模式

適配器模式

1.基本介紹

  • 適配器模式(Adapter Pattern)將某個類的接口轉換成客戶端指望的另外一個接口表示,主要目的是兼容性,讓本來因接口不匹配不能工做的兩個類能夠協同工做,其別名爲包裝器(Wrapper)
  • 適配器模式屬於結構型模式
  • 分爲三類:類配置器模式、對象配置器模式、接口適配器模式

2.工做原理

  • 適配器模式:將一個類的接口轉換爲另外一個接口,讓本來接口不兼容的類能夠兼容
  • 從用戶的角度看不到被適配者,是解耦的
  • 用戶調用適配器轉化出來的目標接口方法,適配器再調用被適配者的相關接口方法
  • 用戶收到反饋結果,感受只是和目標接口交互

3.類適配器

1.介紹

  • Adapter類,經過繼承src類,實現dst類接口,完成src->dst的適配java

  • 做用:將本來不兼容的接口融合在一塊兒工做spring

2. 工做原理圖

3.代碼實現示例

定義Voltage220Vmvc

//被適配對象:模擬220V的插座
public class Voltage220V {
	private int src = 220;
	//輸出220V電壓
	public int output220V() {
		System.out.println("電壓="+src+"伏");
		return src;
	}
}

定義一個適合用戶使用的接口app

public interface IVoltage5V {
	public int output5V();
}

由一個適配器來繼承被適配的對象Voltage220V,同時實現用戶適合的接口,在這之中進行轉換框架

public class VoltageAdapter extends Voltage220V implements IVoltage5V {
	@Override
	public int output5V() {
		// TODO Auto-generated method stub
		int src = output220V();
		//模擬src->dst的適配
		int dst =src/44;
		return dst;
	}
}

定義一個phone,這裏充當適配器模式中的使用者,所以在這裏聚合接口IVoltage5V,遵照ide

依賴倒置原則this

public class Phone {
    //定義手機的充電功能,聚合一個充電器接口
	public void charging(IVoltage5V iVoltage5V) {
		int src = iVoltage5V.output5V();
		System.out.println("輸出"+src+"V");
	}
}

最後由用戶來決定用哪一個適配器來對手機進行充電spa

public class client {
	public static void main(String[] args) {
		Phone phone = new Phone();
        //使用VoltageAdapter充電器對手機進行充電
		phone.charging(new VoltageAdapter());
	}
}

以上爲對工做原理圖的實現,參考該例子的實現思想和結構code

4.類配置器小結

  • java是單繼承機制,因此類適配器須要繼承src類這一點是一個缺點,並且這要求dst必須是一個接口,有必定侷限性
  • src類的方法都在Adapter中暴露出來
  • 優勢:Adapter繼承了src類,因此它能夠根據需求重寫src類的方法,使得Adapter的靈活性增長了

4.對象適配器

1.介紹

  • 與類適配器的思想相同,不一樣的是它對Adapter類作修改,不是繼承src類,而是聚合src對象,持有他的實例,以解決兼容性的問題
  • 根據"合成複用原則",在系統中儘可能使用關聯關係來替代繼承關係
  • 適配器模式中比較經常使用的一種

2.工做原理圖

3.代碼示例

VoltageAdapter再也不繼承Voltage220V,而是直接聚合對象

public class VoltageAdapter implements IVoltage5V {

    //聚合Voltage220V對象
	private Voltage220V voltage;
	public VoltageAdapter(Voltage220V voltage) {
		// TODO Auto-generated constructor stub
		this.voltage = voltage;
	}
	
	@Override
	public int output5V() {
		// TODO Auto-generated method stub
        int dst=0;
        if(voltage!=null){
            int src = voltage.output220V();
            //模擬src->dst 
            dst =src/44;
        }
        	return dst;
	}
}

使用上

public class client {
	public static void main(String[] args) {
		Phone phone = new Phone();
        //構造時須要傳入被適配對象
		phone.charging(new VoltageAdapter(new Voltage220V()));
	}
}

4.對象適配器小結

  • 使用聚合代替了繼承,解決了類適配器必須繼承src的侷限性問題,也再也不要求dst必須是接口
  • 使得更加靈活

5.接口適配器(缺省適配器)

1.定義

  • 當不須要實現接口中的所有方法時,只要定義一個抽象類繼承接口,給每個方法默認實現(空方法),以後該抽象類的子類只須要有選擇性的重寫某些方法來實現需求
  • 適用於一個接口不想使用其全部的方法

2.工做圖解

3.代碼示例

定義接口

public interface Interface2 {
	public void m1();
	public void m2();
	public void m3();	
}

默認實現接口中的方法

public class AbsA implements Interface2{
	@Override
	public void m1() {
		// TODO Auto-generated method stub
	}
	@Override
	public void m2() {
		// TODO Auto-generated method stub	
	}
	@Override
	public void m3() {
		// TODO Auto-generated method stub
	}
}

使用適配器時繼承AbsA或者在建立AbsA的時候能夠選擇性的重寫某些方法

//建立對象的時候重寫
AbsA a = new AbsA() {
    @Override
    public void m2() {
        // TODO Auto-generated method stub
        //進行方法實現
        super.m2();
    }
};

6.適配器模式在springMVC框架中的分析

模擬適配器調用流程

1.類圖分析以下

DispatchServlet中首先獲得一個Controller類型,咱們經過該Controller類型來獲取HandlerAdapter的對應適配器類型,獲得這個適配器以後咱們就能夠調用對應的Controller的doHandler()方法

2.本身編寫代碼模擬實現

  1. 定義HandlerAdapter
//定義一個Adapter接口
public interface HandlerAdapter {
    //判斷是否爲對應的Controller類型
	public boolean supports(Object handler);
    //執行對應的控制器方法
	public void handler(Object handler);
}

//實現多種適配器類
class SimpleHandlerAdapter implements HandlerAdapter{
	@Override
	public boolean supports(Object handler) {
		return (handler instanceof SimpleController);
	}
	@Override
	public void handler(Object handler) {	
		((SimpleController)handler).doSimpleHandler();
	}
}
class HttpHandlerAdapter implements HandlerAdapter{

	//判斷是否爲對應的Controller類型
	@Override
	public boolean supports(Object handler) {
		return (handler instanceof HttpController);
	}
	@Override
	public void handler(Object handler) {
		//執行對應的控制器方法
		((HttpController)handler).doHttpHandler();
	}
}

class AnnotationHandlerAdapter implements HandlerAdapter{

	//判斷是否爲對應的Controller類型
	@Override
	public boolean supports(Object handler) {
		return (handler instanceof AnnotationController);
	}
	@Override
	public void handler(Object handler) {
		//執行對應的控制器方法
		((AnnotationController)handler).doAnnotationHandler();
	}
}
  1. 定義Controller
//模擬Controller的實現和各自的doHandler()方法
public interface Controller {

}

class HttpController implements Controller{
	public void doHttpHandler() {
		System.out.println("HttpHandler....");
	}
}
class AnnotationController implements Controller{
	public void doAnnotationHandler() {
		System.out.println("AnnotationHandler....");
	}
}
class SimpleController implements Controller{
	public void doSimpleHandler() {
		System.out.println("SimpleHandler....");
	}
}
  1. DispatchServlet類,這裏先用list來模擬SpringMVC中配置的全部適配器,doDispatch中模擬SpringMVC從request中獲取handler對象
public class DispatchServlet {
	//模擬配置適配器
	public static List<HandlerAdapter> handlerAdapters= new ArrayList<>();
	static {
		handlerAdapters.add(new AnnotationHandlerAdapter());
		handlerAdapters.add(new HttpHandlerAdapter());
		handlerAdapters.add(new SimpleHandlerAdapter());
	}
	
	public void doDispatch() {
		//模擬SpringMVC從request中獲取handler的對象
		
		//適配器在這裏能夠獲取匹配的Controller
		AnnotationController controller = new AnnotationController();
//		SimpleController controller = new SimpleController();
//		HttpController controller = new HttpController();
		
		//經過controller獲取適配器
		HandlerAdapter adapter = getHandler(controller);
		
		//經過適配器執行對應的Controller方法
		adapter.handler(controller);
		
	}

	private HandlerAdapter getHandler(Controller controller) {
		// 模擬源碼:經過遍歷的方式來匹配適配與controller類型
		for(HandlerAdapter handler : this.handlerAdapters) {
			if(handler.supports(controller)) {
				return handler;
			}
		}
		return null;
	}
	
	public static void main(String[] args) {
        //模擬調用
		new DispatchServlet().doDispatch();   //輸出AnnotationHandler......
	}
}

小結

能夠發如今doDispatch中咱們獲取適配器的時候傳入了什麼類型的Controller就可以獲取對應的適配器,也自動的去調用對應的Controller執行Handler,在這一步徹底能夠適應傳入的Controller,不會由於傳入不一樣的Controller代碼失去做用,增長了靈活性,並且**擴展功能時只須要增長對應的適配器模塊和Controller模塊,配置在SpringMVC中,就同樣能夠被使用,代碼不用進行改動,這就是適配器模式的關鍵做用

相關文章
相關標籤/搜索