文章目录
- 适配器模式
- 1.适配器模式介绍
- 2.适配器模式角色
- 3.适配器模式的实现
- 需求
- 现有
- 工具类
- 3.1继承方式实现适配器
- 3.2组合的方式
- 3.3适配器模式实现扩展
- 3.4文档结构及名称
- 3.5总结
- 4.适配器模式的使用
- 4.1使用适配器可以在不更改原有类的基础上增加新类,这样出现bug也是在新类中,比在原有类的基础上修改好的多。
- 4.2修改原有类需要对原有类进行测试,如果只是改动比较小,但是测试比较麻烦的类,使用适配器的代价小的多。
- 4.3版本升级,新版本兼容旧版本。
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种设计模式