实例探索Java模式之路——适配器模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dingjianmin/article/details/72971060
什么是结构模式:

结构模式描述的是如何将类或者对象结合在一起形成更大的结构,结构模式描述两种不同的东西:类与类的实体。


结构模式分为:类的结构模式和对象的结构模式

类的结构模式:使用继承来把类,接口等组合在一起,以形成更大的结构。当一个类从父类继承并实现某个接口时,这个新的类就把父类的结构和接口的结构组合起来。类的结构模式是静态的。


对象的结构模式:描述怎样把各种不同类型的对象组合在一起,以实现新的功能的方法,对象的结构模式是动态的。



适配器模式


1、把一个类的接口变换成客户端所期待的另一种接口,从而是原本因接口不匹配而无法在一起工作的两个类能够在一起工作。


2、变压器的例子,我们知道美国的电压110,中国电压220,如何把从美国带回来的电饭煲在中国使用,这就需要用到变压器进行调节了,变压器也就是110电压的电饭煲在220电压下工作的适配器。


//美国的生活电压110V
public interface USA110 {
// 目标角色
// 美国110电压接口
public void connect();


}


//110电压实现类
public class USA110impl implements USA110 {


@Override
public void connect() {
System.out.println("110接通电源,开始工作。。。。。。");
}


}


//中国的生活电压220V
public interface CN220 {
// 源角色
// 中国220电压接口
public void connect();


}


//220电压实现类
public class CN220impl implements CN220 {


@Override
public void connect() {
System.out.println("220接通电源,开始工作。。。。。。");
}


}


//110v的电饭煲
public class ElectricCooker {


private USA110 usa110;//110电饭煲要用110电压接口


public ElectricCooker(USA110 usa110) {
super();
this.usa110 = usa110;
}
public void cook(){
usa110.connect();//通电
System.out.println("开始做饭。。。");
}

}


//电压适配器
//为了能够适配110V电饭煲的电源接口,我们要继承110接口
//适配器角色,实现目标角色接口
public class PowerAdaptor implements USA110 {


/* 继承110接口,可以使用美国电饭煲,有持有220引用可以用220工作 */
private CN220 cn220;// 用220v=接口进行适配


public PowerAdaptor(CN220 cn220) {
super();
this.cn220 = cn220;
}


@Override
public void connect() {
cn220.connect();
}


}


//测试类
public class AdapterTest {
public static void main(String[] args) {


CN220 cn220 = new CN220impl();// 220电压


PowerAdaptor adaptor = new PowerAdaptor(cn220);// 电源适配


ElectricCooker cooker = new ElectricCooker(adaptor);// 使用110电压


cooker.cook();

}
}

结果打印:
220接通电源,开始工作。。。。。。
开始做饭。。。


可以看出,110的电饭煲开始在220电压下工作了。这就是适配模式。


3、适配器模式有两种形式(类的适配模式和对象的适配模式)


1、类的适配模式:是把适配的类的API转换成目标类的API。





目标角色(target):这就是所期待得到的接口,由于是类适配模式,目标不可以是类。
源角色(adaptee):现在需要适配的接口。
适配角色(adapter):适配模式的核心,把源接口转换成目标接口,这一角色不可以是接口,而必须是具体类。


//目标角色
public interface Target {


//源类也有的方法
void method1();
//源类没有的方法
void method2();
}


public class Adaptee {
//源类含有的方法
public void method1() {

}

}
//适配器角色扩展了源类,同时实现了目标接口
由于源角色没有method2,而目标接口又需要这个方法,所有适配器类实现了这个方法。


public class Adapter extends Adaptee implements Target {


@Override
public void method2() {
// TODO Auto-generated method stub


}


}




2、对象的适配器模式:



对象的适配模式把适配的类的API转换成目标类的API,与类的适配模式不同的是,对象的适配器模式不是使用继承关系连接源类,而是使用委派关系连接到源类。


目标角色:这就是所期待得到的接口,目标可以是具体的或者抽象的类。
源角色:现在需要适配的接口。
适配角色:适配模式的核心,把源接口转换成目标接口,这一角色不可以是接口,而必须是具体类。


一个指方为圆的例子,就是采用对象的适配模式。



//目标角色接口,需要圆形
public interface BallTarget {


// 面积
double Area();


// 体积
double Volume();


// 半径取值


double getRadius();


// 半径赋值


void setRadius(double radius);
}




//方形图,源角色
public class Cube {


private double width;


// 构造方法
public Cube(double width) {
super();
this.width = width;
System.out.println("方图的有参构造方法");
System.out.println("长度"+width);
}


// 体积
public double Volueme() {
return width * width * width;
}


// 面积
public double FaceArea() {
return width * width;
}


public double getWidth() {
return width;
}


public void setWidth(double width) {
this.width = width;
}


}




//适配器角色,实现了BallTarget接口,同时扩展了Cube类,
public class MagicAdapter implements BallTarget {


private double radius = 0;


private static final double pi = 3.14D;


private Cube adaptee;


// 构造方法
public MagicAdapter(Cube adaptee) {
super();
this.adaptee = adaptee;//委派
radius = adaptee.getWidth();


System.out.println("适配器的有参构造方法");
System.out.println("半径" + radius);
}


// 面积
@Override
public double Area() {
return pi * 4.0D * (radius * radius);
}


@Override
public double Volume() {
return pi * 4.0D / 3.0D * (radius * radius * radius);
}


public void setRadius(double radius) {
this.radius = radius;
}


@Override
public double getRadius() {
return radius;
}


}


//测试类
public class Client {
public static void main(String[] args) {
Cube adaptee = new Cube(3.0D);


BallTarget bt = new MagicAdapter(adaptee);


System.out.println(bt.Area());
System.out.println(bt.getRadius());
System.out.println(bt.Volume());


bt.setRadius(5.0);


System.out.println(bt.Area());
System.out.println(bt.getRadius());
System.out.println(bt.Volume());
System.out.println();
}
}


结果:
方图的有参构造方法
长度3.0
适配器的有参构造方法
半径3.0
113.04
3.0
113.03999999999999
314.0
5.0
523.3333333333334


4、缺省适配模式:
为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原来接口进行扩展。它是适配模式的一个特例。


一个简单例子:


//目标角色
public interface SubjectTarget {


void leanJava();


void leanC();


void leanMath();


void leanEnglish();


void otherMethod();
}




//缺省适配器,空实现目标角色接口
public abstract class defaultAdapter implements SubjectTarget {


@Override
public void leanJava() {
// TODO Auto-generated method stub


}


@Override
public void leanC() {
// TODO Auto-generated method stub


}


@Override
public void leanMath() {
// TODO Auto-generated method stub


}


@Override
public void leanEnglish() {
// TODO Auto-generated method stub


}


@Override
public void otherMethod() {
// TODO Auto-generated method stub


}


}




//客户端角色,继承缺省适配器,没有必要全部实现目标角色的全部方法
public class studClient extends defaultAdapter {


@Override
public void leanJava() {
super.leanJava();
System.out.println("学习Java!");
}


@Override
public void leanEnglish() {
super.leanEnglish();
System.out.println("学习英语!");
}


public void play() {


System.out.println("自己的其他方法!");
}


public static void main(String[] args) {
studClient st = new studClient();


st.leanJava();
st.leanMath();
}
}




5、使用场景:


任何时候,如果不准备实现一个接口的所有方法时,就可以采用此模式。


缺省适配模式的中心是一个缺省适配类,是抽象的,这个类不应当实例化,而且实例化也是没用的。



通过这些实例,相信对该模式有了进一步的认识。

每天努力一点,每天都在进步。




阅读更多
换一批

没有更多推荐了,返回首页