结构型模式
这篇博文刚开始讲述设计模式中另一大分类:结构型模式,共7种适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
这其中对象的适配器模式是其他各种结构型模式的起源,他们的衍生关系图,如下图:
适配器模式
适配器模式,有时也称作包装模式,是指将某一个类的接口适配转化成用户所期望的另一接口的情况,
其目的是解决由于接口不匹配所造成的类的兼容性问题。适配器模式又可分为三种:类的适配器模式,对象的适配器模式,接口的适配器模式。先来了解一下类的适配器模式类的适配器模式
其核心的思想是,现存有一个原始类,拥有一些方法,用户期望的目标接口除了原始类拥有的原始方法,还需要有新增一些其他方法,这里通过Adapter类对原始类的方法扩展到目标接口。例如,现存Sms 类,拥有发送短信的方法,用户期望的适配目标接口除了有发送短信,还有发送延时短信,可以建立一个适配类将Sms 类适配到目标接口,类图如下:
详细代码如下:
Sms 类,拥有发送短信的方法
public class Sms {
public void sendSms() {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "sendSms()"));
}
}
目标接口,除了有发送短信,还有发送延时短信
public interface Sender {
public void sendSms();
public void sendDelaySms(long delay);
}
适配类将Sms 类适配到目标接口
public class SmsAdapter extends Sms implements Sender {
@Override
public void sendDelaySms(long delay) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "sendDelaySms()"));
}
}
测试类代码:
public class WorkClass {
public void test() {
Sender smsSender= new SmsAdapter();
smsSender.sendSms();
smsSender.sendDelaySms(1000*60*60);
}
}
输出结果:
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.SmsAdapter.sendSms() called!
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.SmsAdapter.sendDelaySms() called!
目标接口Sender的实现类具有了原始类Sms的功能方法。
对象的适配器模式
对象的适配器模式的核心思路与类的适配器模式不同,适配类不是继承原始类,而是持有一个原始类的实例,以达到适配目标接口这一同样的目的。先看类图:
新增SmsWrapper类
public class SmsWrapper implements Sender {
private Sms sms;
@Override
public void sendDelaySms(long delay) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "sendDelaySms()"));
}
@Override
public void sendSms() {
if (null != sms) {
sms.sendSms();
}
}
public SmsWrapper(Sms smsobj) {
this.sms = smsobj;
}
}
测试类代码:
public class WorkClass {
public void test() {
Sender smsSender = new SmsWrapper(new Sms());
smsSender.sendSms();
smsSender.sendDelaySms(1000 * 60 * 60);
}
}
输出结果:
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.Sms.sendSms() called!
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.SmsWrapper.sendDelaySms() called!
目的输出与类的适配器一样,只是实现方式不一样。
- 第三种适配器模式是接口的适配器模式
接口的适配器模式的应用场景是这样子的,现存一个接口,它包括一系列等实现的方法,如果我们写一个类去实现这个接口,就必须全部实现接口的所有方法,可有时这些方法并不是我们全部都想要的,显然这是一种冗余。接口的适配器模式正是为了解决上面所述这种情况,其核心思想是,借助一个抽象类(abstract class)去实现原始接口,这样抽象类的子类,就可以不必直接与原始接口打交道而只要重写抽象类的一些我们想要的方法就可以了。类图如下:
在实际开发中,我们会遇到某接口中定义了太多的方法,以致于有时我们在一些实现类中并不是都需要用到。
代码:
Setter 接口:
public interface Setter {
public void setText(String text);
public void setBitmapDrawable(int id);
}
WrapperSetter 抽象类:
public abstract class WrapperSetter implements Setter {
@Override
public void setText(String text) {}
@Override
public void setBitmapDrawable(int id) {}
}
实现子类:
public class TextViewSetter extends WrapperSetter {
@Override
public void setText(String text) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "setText()"));
}
}
public class ImageViewSetter extends WrapperSetter {
@Override
public void setBitmapDrawable(int id) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "setBitmapDrawable()"));
}
}
测试类代码:
public class WorkClass {
public void test() {
Setter setterText = new TextViewSetter();
Setter setterImage = new ImageViewSetter();
setterText.setText("");
setterImage.setBitmapDrawable(R.drawable.a500cg_btn);
}
}
输出结果:
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.TextViewSetter.setText() called!
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.ImageViewSetter.setBitmapDrawable() called!
- 结语
三种适配器模式分别有各自不同应用场景:
类适配器模式:需求将一个类转换成实现另一个新接口的类时,可以此模式,创建一个新类,继承原有的类并实现目标的接口即可。
对象适配器模式:需求将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的实现目标接口的方法中,调用原类实例的方法即可。
接口适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,写子类继承抽象类的时候,覆写需要的方法即可。