概念
桥接模式是一种结构型设计模式,它通过将抽象与其实现分离来解耦。它使用接口(抽象类)作为桥梁,将一个抽象类与其实现类的代码分别独立开来,从而使它们可以各自独立地变化。桥接模式的核心思想是“组合优于继承”。
示例
为了更好地理解桥接模式,我们来看一个简单的示例:假设有一个形状类,其中有一个颜色属性。此时,如果我们使用继承来实现不同颜色的形状类,就需要创建许多子类,使代码结构变得复杂且难以维护。而使用桥接模式,则可以将形状和颜色分别抽象出来,从而将它们独立开来。
下面是一个简单的代码示例:
public interface Color {
String getColor();
}
public class Red implements Color {
@Override
public String getColor() {
return "红色";
}
}
public class Blue implements Color {
@Override
public String getColor() {
return "蓝色";
}
}
public abstract class Shape {
protected Color color;
public Shape(Color color) {
this.color = color;
}
public abstract void draw();
}
public class Rectangle extends Shape {
public Rectangle(Color color) {
super(color);
}
@Override
public void draw() {
System.out.println("绘制一个" + color.getColor() + "的矩形");
}
}
public class Circle extends Shape {
public Circle(Color color) {
super(color);
}
@Override
public void draw() {
System.out.println("绘制一个" + color.getColor() + "的圆形");
}
}
在上面的代码中,我们首先定义了一个颜色接口,并分别实现了红色和蓝色。然后,我们定义了一个抽象的形状类,其中有一个颜色属性和一个抽象方法draw()。最后,我们实现了具体的矩形和圆形类,并在构造函数中传入了一个颜色对象。
这样,我们就将形状和颜色分别抽象出来,从而实现了解耦。当我们需要创建不同颜色的形状时,只需要创建不同颜色的对象并传入即可。
Android应用
在Android应用开发中,桥接模式通常用于将业务逻辑和UI分离。例如,在MVP(Model-View-Presenter)模式中,Presenter通常充当桥接的角色,将View和Model分离开来。Presenter通过接口(抽象类)与View进行交互,并通过Model来获取数据。
下面是一个简单的MVP示例:
public interface LoginView {
void showProgress();
void hideProgress();
void setUsernameError();
void setPasswordError();
void navigateToHome();
}
public interface LoginPresenter {
void validateCredentials(String username, String password);
}
public class LoginPresenterImpl implements LoginPresenter {
private LoginView loginView;
private LoginModel loginModel;
public LoginPresenterImpl(LoginView loginView) {
this.loginView = loginView;
loginModel = new LoginModelImpl();
}
@Override
public void validateCredentials(String username, String password) {
if (TextUtils.isEmpty(username)) {
loginView.setUsernameError();
return;
}
if (TextUtils.isEmpty(password)) {
loginView.setPasswordError();
return;
}
loginView.showProgress();
loginModel.login(username, password, new LoginModel.OnLoginFinishedListener() {
@Override
public void onUsernameError() {
loginView.hideProgress();
loginView.setUsernameError();
}
@Override
public void onPasswordError() {
loginView.hideProgress();
loginView.setPasswordError();
}
@Override
public void onSuccess() {
loginView.hideProgress();
loginView.navigateToHome();
}
});
}
}
public interface LoginModel {
interface OnLoginFinishedListener {
void onUsernameError();
void onPasswordError();
void onSuccess();
}
void login(String username, String password, OnLoginFinishedListener listener);
}
public class LoginModelImpl implements LoginModel {
@Override
public void login(final String username, final String password, final OnLoginFinishedListener listener) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (username.equals("user") && password.equals("password")) {
listener.onSuccess();
} else if (!TextUtils.isEmpty(username)) {
listener.onPasswordError();
} else {
listener.onUsernameError();
}
}
}, 2000);
}
}
在上面的代码中,我们定义了一个LoginView接口,其中包含了一些用于显示UI的方法。然后,我们定义了一个LoginPresenter接口,它与LoginView接口相连,并通过LoginModel来获取数据。最后,我们实现了具体的LoginPresenterImpl和LoginModelImpl类。
通过这种方式,我们将UI和业务逻辑分开,从而使代码结构更清晰,易于维护。
源码解析
在Android源码中,桥接模式也有广泛的应用。例如,在View系统中,View和ViewGroup之间就采用了桥接模式来实现解耦。
在View系统中,View是Android系统中的基本UI组件,而ViewGroup则是一种容器组件,用于将多个View组合在一起。在这两个组件中,都有一个名为LayoutParams的内部类,用于描述组件的布局参数。
在早期的Android版本中,View和ViewGroup之间是通过继承来实现布局参数的传递的。但是这样会导致代码结构复杂且难以维护,因此在Android 2.2版本中,Google采用了桥接模式来重构View系统,从而使其更加灵活和易于维护。
下面是一个简单的代码示例,展示了View和ViewGroup之间是如何通过桥接模式来传递布局参数的:
public class View {
private LayoutParams mLayoutParams;
public void setLayoutParams(LayoutParams params) {
mLayoutParams = params;
}
public LayoutParams getLayoutParams() {
return mLayoutParams;
}
public static class LayoutParams {
// 布局参数的属性
}
}
public class ViewGroup extends View {
private ArrayList<View> mChildList = new ArrayList<>();
public void addView(View child) {
mChildList.add(child);
child.setParent(this);
}
public void removeView(View child) {
mChildList.remove(child);
child.setParent(null);
}
public void removeAllViews() {
for (View child : mChildList) {
child.setParent(null);
}
mChildList.clear();
}
public static class LayoutParams extends View.LayoutParams {
// 布局参数的属性
}
}
在上面的代码中,我们首先定义了一个View类,并在其中包含了一个LayoutParams内部类。然后,我们定义了一个ViewGroup类,它继承自View,并增加了一个mChildList成员变量和相关的方法,用于管理子View。
最后,我们在ViewGroup中定义了一个LayoutParams内部类,并继承自View.LayoutParams。通过这种方式,我们将布局参数从View中分离出来,使得View和ViewGroup之间的关系更加清晰。
总之,桥接模式是一种常用的设计模式,它可以帮助我们将抽象和实现分离开来,从而实现解耦。