23种设计模式----适配器模式----结构模式

可紊 提交于 2019-11-30 15:09:17


23种设计模式

适配器模式

1.适配器模式介绍

引入:显示生活中,有许许多多的的电器在被使用,但是我们普通家用电线的电压是220V(一般)。但是家里的电器却又很多种:
手机充电:5V
手电筒:12V、5V
电视机:220V
笔记本:12V
(电器电压不一定正确)
。。。。。。。。
那么,为什么只提供一种电压却满足了这么不同电压需求的电器。
原因就是每一种电器都有各自的电压转换器(变压器),笔记本是充电适配器(外)电视机(内)手机充电头(电源适配器)
所以,生活中处处可见各种各样的适配器。

在程序世界中,经常会存在有的程序无法直接使用,需要做适当的变换之后才能使用的情形(源自《图解设计模式》)。适配器模式就是连接“现有程序”和“目标程序”的中间程序。

2.适配器模式角色

通俗的理解:
需求-Target
适配器-Adapter
现有-Adaptee
使用-Client
专业的解释:
Target-对象
Client-请求者
Adaptee-被适配
Adapter-适配

3.适配器模式的实现

适配模式的实现主要分为2种:继承的方式和组合的方式。

需求

一个接口:玩和吃

public interface PeopleAction {

	void playNeed();
	
	void eatNeed();
	
}

现有

一个类:名字和年龄,玩和吃方法

import com.startime.adapter.utils.PeopleEatUtil;
import com.startime.adapter.utils.PeoplePlyUtil;


public class People{

	protected String name;
	
	protected int age;
	
	protected String string;
	
	public void setString(String string){
		this.string = string;
	}
	 
	public People(String name,int age){
		this.name = name;
		this.age = age;
	}

	public void playHave(){
		PeoplePlyUtil.p(string, name, age);
	}

	public void eatHave(){
		PeopleEatUtil.e(string, name, age);
	}
}

工具类

public class PeopleEatUtil {
	
	public static void showTime(){
		PeoplePlyUtil.showTime();
	}
	
	public static void eat(String string){
		System.out.println(string);
	}
	
	public static void eat(String name,int age){
		System.out.println("我叫"+name+",今年"+age+"岁!");
	}
	
	public static void e(String string,String name,int age){
		showTime();
		eat(name, age);
		eat(string);
	}
}
import java.text.SimpleDateFormat;
import java.util.Date;

public class PeoplePlyUtil {

	public static void play(String string){
		System.out.println(string);
	}
	public static void play(String name,int age){
		System.out.println("我叫"+name+",今年"+age+"岁!");
	}
	public static void showTime(){
		System.out.print(new SimpleDateFormat("HH:mm:ss").format(new Date())+"\t");
	}
	public static void p(String string,String name,int age){
		showTime();
		play(name, age);
		play(string);
	}
}

3.1继承方式实现适配器

定义适配器:

import com.startime.adapter.domain.PeopleAction;
import com.startime.adapter.domain.People;


public class ChildrenExtend extends People implements PeopleAction{
	
	public ChildrenExtend(String name, int age) {
		super(name, age);
	}

	@Override
	public void playNeed() {
		super.setString("我玩王者荣耀");
		super.playHave();
	}

	@Override
	public void eatNeed() {
		super.setString("我吃冰淇淋");
		super.eatHave();
	}

}
import com.startime.adapter.domain.PeopleAction;
import com.startime.adapter.domain.People;


public class TeenagerExtend extends People implements PeopleAction{

	public TeenagerExtend(String name, int age) {
		super(name, age);
	}

	@Override
	public void playNeed() {
		super.setString("我玩足球");
		super.playHave();
	}

	@Override
	public void eatNeed() {
		super.setString("我吃麻辣烫");
		super.eatHave();
	}

}

import com.startime.adapter.domain.PeopleAction;
import com.startime.adapter.domain.People;


public class WrinklyExtend extends People implements PeopleAction{
	
	public WrinklyExtend(String name, int age) {
		super(name, age);
	}

	@Override
	public void playNeed() {
		super.setString("我玩高尔夫球");
		super.playHave();
	}

	@Override
	public void eatNeed() {
		super.setString("我吃绿豆羹");
		super.eatHave();
	}
	
	
}
import com.startime.adapter.domain.PeopleAction;
import com.startime.adapter.domain.People;


public class OlderExtend extends People implements PeopleAction{
	
	public OlderExtend(String name, int age) {
		super(name, age);
	}

	@Override
	public void playNeed() {
		super.setString("我玩中国象棋");
		super.playHave();
	}

	@Override
	public void eatNeed() {
		super.setString("我吃流食");
		super.eatHave();
	}

}

使用:

public class MainExtend {

	public static void main(String[] args) {
		ChildrenExtend c = new ChildrenExtend("小胖", 9);
		c.playNeed();
		c.eatNeed();
		TeenagerExtend t = new TeenagerExtend("张峰", 19);
		t.playNeed();
		t.playNeed();
		WrinklyExtend w = new WrinklyExtend("中山", 35);
		w.playNeed();
		w.eatNeed();
		OlderExtend o = new OlderExtend("X老", 88);
		o.playNeed();
		o.eatNeed();
	}

}

3.2组合的方式

实现适配器:

import com.startime.adapter.domain.People;
import com.startime.adapter.domain.PeopleAction;

public class ChildrenGroup implements PeopleAction{
	
	private People children = null;
	
	public ChildrenGroup(String name,int age){
		children = new People(name, age);
	}

	@Override
	public void playNeed() {
		children.setString("我玩手机游戏");
		children.playHave();
	}

	@Override
	public void eatNeed() {
		children.setString("我吃冰淇淋");
		children.eatHave();
	}
	
}
import com.startime.adapter.domain.People;
import com.startime.adapter.domain.PeopleAction;

public class TeenagerGroup implements PeopleAction{

	private People teenager = null;
	
	public TeenagerGroup(String name,int age){
		teenager = new People(name, age);
	}
	
	@Override
	public void playNeed() {
		teenager.setString("我玩足球");
		teenager.playHave();
	}

	@Override
	public void eatNeed() {
		teenager.setString("我吃辣条");
		teenager.eatHave();
	}
	
}
import com.startime.adapter.domain.People;
import com.startime.adapter.domain.PeopleAction;

public class WrinklyGroup implements PeopleAction{
	
	private People wrinkly = null;
	
	public WrinklyGroup(String name,int age){
		wrinkly = new People(name, age);
	}

	@Override
	public void playNeed() {
		wrinkly.setString("我玩攀岩");
		wrinkly.playHave();
	}

	@Override
	public void eatNeed() {
		wrinkly.setString("我吃肉");
		wrinkly.eatHave();
	}

}
import com.startime.adapter.domain.People;
import com.startime.adapter.domain.PeopleAction;

public class OlderGroup implements PeopleAction{
	
	private People older = null;
	
	public OlderGroup(String name,int age){
		older = new People(name, age);
	}

	@Override
	public void playNeed() {
		older.setString("我玩象棋");
		older.playHave();
	}

	@Override
	public void eatNeed() {
		older.setString("我吃流食");
		older.eatHave();
	}

}

使用:

public class MainGroup {
	public static void main(String[] args) {
		ChildrenGroup c = new ChildrenGroup("小胖", 9);
		c.playNeed();
		c.eatNeed();
		TeenagerGroup t = new TeenagerGroup("张峰", 19);
		t.playNeed();
		t.playNeed();
		WrinklyGroup w = new WrinklyGroup("中山", 35);
		w.playNeed();
		w.eatNeed();
		OlderGroup o = new OlderGroup("X老", 88);
		o.playNeed();
		o.eatNeed();
	}
}

3.3适配器模式实现扩展

问题:需求中的接口如果比较多,在实现适配器中,适配器可能用到很少的接口,会造成许多接口无用的实现。
原理:使用一个中间类,中间类实现接口(空语句实现),然后适配器继承中间类,利用子类覆盖父类的方法实现需求的接口,其他接口不用实现。
缺陷:
现有类的属性与方法需要被孙子类访问到(可以是方法访问或者属性权限控制)。
比如使用protected修饰类的属性或者增加protected方法访问类的属性。
接口:

public interface PersonEatInterface {

	void eatIceCream();
		
	void eatHotpot();
	
	void eatMungBeanSoup();
	
	void eatFluids();
}
public interface PersonPlayInterface {

	void playGame();

	void playSoccer();

	void playGolf();

	void playChess();
}

中间类:

import com.startime.adapter.domain.People;


public class PeopleBasic extends People implements PersonEatInterface,PersonPlayInterface{

	public PeopleBasic(String name, int age) {
		super(name, age);
	}

	@Override
	public void playGame() {
		super.playHave();
	}

	@Override
	public void playSoccer() {
		super.playHave();
	}

	@Override
	public void playGolf() {
		super.playHave();
	}

	@Override
	public void playChess() {
		super.playHave();
	}

	@Override
	public void eatIceCream() {
		super.eatHave();
	}

	@Override
	public void eatHotpot() {
		super.eatHave();
	}

	@Override
	public void eatMungBeanSoup() {
		super.eatHave();
	}

	@Override
	public void eatFluids() {
		super.eatHave();
	}
	public void setString(String string){
		super.setString(string);
	}

}

适配器:

public class ChildrenExtendsAndInterface extends PeopleBasic{

	public ChildrenExtendsAndInterface(String name, int age) {
		super(name, age);
	}

	@Override
	public void playGame() {
		super.setString("我玩吃鸡");
		super.playGame();
	}

	@Override
	public void eatIceCream() {
		super.setString("我吃冰淇淋");
		super.eatIceCream();
	}
	
}
public class TeenagerExtendsAndInterface extends PeopleBasic{

	public TeenagerExtendsAndInterface(String name, int age) {
		super(name, age);
	}

	@Override
	public void playSoccer() {
		super.setString("我玩足球");
		super.playSoccer();
	}

	@Override
	public void eatHotpot() {
		super.setString("我吃麻辣烫");
		super.eatHotpot();
	}
	

}

public class WrinklyExtendsAndInterface extends PeopleBasic{

	public WrinklyExtendsAndInterface(String name, int age) {
		super(name, age);
	}

	@Override
	public void playGolf() {
		super.setString("我玩高尔夫球");
		super.playGolf();
	}

	@Override
	public void eatMungBeanSoup() {
		super.setString("我吃绿豆羹");
		super.eatMungBeanSoup();
	}

}

public class OlderExtendsAndInterface extends PeopleBasic{

	public OlderExtendsAndInterface(String name, int age) {
		super(name, age);
	}

	@Override
	public void playChess() {
		super.setString("我玩象棋");
		super.playChess();
	}

	@Override
	public void eatFluids() {
		super.setString("我吃流食");
		super.eatFluids();
	}

}

使用:

import java.util.ArrayList;
import java.util.List;

public class MainExtendsAndInterface {
	
	public static void main(String[] args) {
		List<PeopleBasic> list = new ArrayList<PeopleBasic>();
		list.add(new ChildrenExtendsAndInterface("小胖", 9));
		list.add(new TeenagerExtendsAndInterface("张峰", 19));
		list.add(new WrinklyExtendsAndInterface("中山", 35));
		list.add(new OlderExtendsAndInterface("X老", 88));
		for (PeopleBasic object : list) {
			object.playChess();
			object.playGame();
			object.playGolf();
			object.playSoccer();
			object.eatFluids();
			object.eatHotpot();
			object.eatIceCream();
			object.eatMungBeanSoup();
		}
	}
}

3.4文档结构及名称

这里写图片描述

3.5总结

适配器解决连接旧类与新类的问题,主要有继承和组合两种方式;继承方式就是适配器继承旧类实现新类需求的接口,在新类的需求接口中合理的调用旧类现有的方法,实现新类的需求;组合方式是在适配器中增加旧类的属性,在实现新类的接口中,合理的通过旧类对象来调用旧类的方法,实现新类的需求;当接口中的方法较多时,可以使用中间类空语句或者转发(不改变任何东西,只是转发请求)实现接口,在中间类的子类中具体实现需要实现的接口;使用中间类要求旧类的方法在新类中能够实现调用,要么是权限限定关键词限定作用域,或者提供专门的访问方法,才能实现中间类的转发,进而实现适配器;使用适配器需要旧类方法和新类方法有一定的联系,如果完全没有任何显示或者隐含的联系,强行使用适配器只会增加工作的难度和工作量。

4.适配器模式的使用

4.1使用适配器可以在不更改原有类的基础上增加新类,这样出现bug也是在新类中,比在原有类的基础上修改好的多。

4.2修改原有类需要对原有类进行测试,如果只是改动比较小,但是测试比较麻烦的类,使用适配器的代价小的多。

4.3版本升级,新版本兼容旧版本。

23种设计模式

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!