Android | java安卓上位机开发 策略模式实现多连接方式的扩展
在进行安卓上位机项目开发时,最初的通讯方式只有一种——低功耗蓝牙,后续由于项目需求,新增了wifi通讯模式,在新增通讯模式后,需要对原有代码进行重构,以实现新增功能,并且需要考虑到增加其他通讯方式的扩展性,于是尝试了两种方式:
两种方案均通过工厂模式创建对象,核心差异在于 “通讯逻辑与设备属性的绑定方式”:
- 多态(继承抽象类):将设备属性(名称、地址等)和通讯方法(连接、发送等)封装在抽象类中,具体通讯方式(蓝牙、TCP)通过继承抽象类实现。
例:AbstractDevice定义设备通用属性和抽象通讯方法,BleDevice、TcpDevice分别实现蓝牙和 TCP 的具体逻辑。 - 策略模式:将通讯逻辑抽离为独立策略接口,设备属性与通讯策略通过 “组合” 关联。
例:ConnectionStrategy接口定义通讯标准,BleStrategy、TcpStrategy实现具体通讯逻辑;Device类持有设备属性,并通过注入不同策略实现通讯方式切换。
方法一——多态:
第一种,也就是最先采用并实现的一种方法,构造一个抽象父类,声明必要的方法,不同连接方式通过继承抽象对象,进行独立的实现,来实现各自的连接方法。
例:
package StrategyPattern.poly;
/**
* 顶层抽象类
*/
public abstract class AbstractDevice {
private String deviceName;
private String address;
private String deviceType;
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
/**
* 设备连接方法
* @return
*/
public abstract boolean connect();
/**
* 设备断开方法
* @return
*/
public abstract boolean disconnect();
/**
* 发送数据
* @param data 数据
* @return
*/
public abstract boolean write(byte[] data);
/**
* 接收数据(在具体的子类中实现,在具体实现中,将接收到的数据进行转发或其他操作)
* @param data 接收到的数据
* @return
*/
public abstract boolean recv(byte[] data);
}
package StrategyPattern.poly;
public class BleDevice extends AbstractDevice{
@Override
public boolean connect() {
return false;
}
@Override
public boolean disconnect() {
return false;
}
@Override
public boolean write(byte[] data) {
return false;
}
@Override
public boolean recv(byte[] data) {
return false;
}
}
package StrategyPattern.poly;
public class TcpDevice extends AbstractDevice{
@Override
public boolean connect() {
return false;
}
@Override
public boolean disconnect() {
return false;
}
@Override
public boolean write(byte[] data) {
return false;
}
@Override
public boolean recv(byte[] data) {
return false;
}
}
方法二——策略模式:
策略模式则是将连接方式抽离为单独的策略接口,使用接口来进行操作。在构造对象时,通过不同的接口实现,来进行不同方式的设备连接。
package StrategyPattern.strategy;
public interface ConnectionStrategy {
public interface ConnectionCallback{
void onConnected();
void onError(Exception e);
void onDisconnected();
void onDataReceived(byte[] data);
}
/**
* 建立连接
* @param callback 连接回调
* @return 连接是否成功启动
*/
boolean connect(ConnectionCallback callback);
/**
* 断开连接
* @return 断开是否成功
*/
boolean disconnect();
/**
* 发送数据
* @param data 要发送的数据
* @return 发送是否成功
*/
boolean writeData(byte[] data);
/**
* 获取连接状态
* @return 是否已连接
*/
boolean isConnected();
/**
* 释放资源
*/
void release();
}
package StrategyPattern.strategy;
public class BleStrategy implements ConnectionStrategy{
private ConnectionCallback callback;
@Override
public boolean connect(ConnectionCallback callback) {
return false;
}
@Override
public boolean disconnect() {
return false;
}
@Override
public boolean writeData(byte[] data) {
return false;
}
@Override
public boolean isConnected() {
return false;
}
@Override
public void release() {
}
}
package StrategyPattern.strategy;
public class TcpStrategy implements ConnectionStrategy{
private ConnectionCallback callback;
@Override
public boolean connect(ConnectionCallback callback) {
return false;
}
@Override
public boolean disconnect() {
return false;
}
@Override
public boolean writeData(byte[] data) {
return false;
}
@Override
public boolean isConnected() {
return false;
}
@Override
public void release() {
}
}
package StrategyPattern.strategy;
public class Device {
private String deviceName;
private String address;
private String deviceType;
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
private ConnectionStrategy strategy;
public Device(ConnectionStrategy strategy){
this.strategy = strategy;
}
public boolean connect(){
return this.strategy.connect(new ConnectionStrategy.ConnectionCallback() {
@Override
public void onConnected() {
// 连接成功回调
}
@Override
public void onError(Exception e) {
// 错误提示
}
@Override
public void onDisconnected() {
// 连接断开回调
}
@Override
public void onDataReceived(byte[] data) {
// 接受到数据
}
});
}
public boolean disconnect(){
// 具体实现
return true;
}
public boolean isConnected(){
// 具体实现
return true;
}
}
总结(让ai总结的)
多态方法(继承抽象类)的优缺点
优点
- 实现简单直接
通过继承抽象类,每个具体设备(如 BleDevice、TcpDevice)直接实现所需方法,符合面向对象的基本设计原则。 - 代码结构清晰
功能和状态集中在一个类中,便于理解和维护。例如,设备的连接状态、生命周期管理都封装在子类中。 - 强类型关联
设备类型与通信方式紧密绑定,适用于设备与通信方式一一对应的场景。例如,BleDevice 只能通过蓝牙通信。
缺点
- 扩展性受限
新增通信方式需要创建新的子类,导致子类数量膨胀。例如,若后续增加 USB、NFC 等通信方式,类的数量会急剧增加。 - 代码复用困难
若不同通信方式有共同逻辑(如数据解析、错误处理),难以在子类间复用,可能导致代码冗余。 - 依赖关系复杂
高层模块直接依赖具体子类,违反依赖倒置原则。例如,若需要切换通信方式,可能需要修改多处代码。 - 回调逻辑处理不便
若通信过程需要异步回调(如连接状态通知),需要在抽象类中预先定义接口或方法,增加设计复杂度。
策略模式的优缺点
优点
- 高扩展性
新增通信方式只需实现ConnectionStrategy接口,无需修改现有代码,符合开闭原则。例如,增加 WiFi 通信只需创建WiFiStrategy类。 - 代码复用性好
可在策略类间共享通用逻辑(如数据缓存、异常处理),通过组合而非继承实现功能复用。 - 松耦合设计
Device类与具体通信实现解耦,便于切换和扩展通信方式。例如,同一设备可在运行时动态切换蓝牙、TCP 等通信策略。 - 便于单元测试
策略类可独立测试,无需依赖具体设备实现,提高测试覆盖率。
缺点
- 类数量增加
每个通信方式需要独立的策略类,可能导致类数量增多,但结构更清晰。 - 状态管理复杂
若通信状态需要在多个策略间共享,需额外设计状态管理机制,增加复杂度。 - 初始设计复杂度高
需要设计抽象策略接口、回调机制等,初期投入成本较高。
浙公网安备 33010602011771号