求一个最佳实践?

有个案例我不知道是否对应哪个设计模式,求一个最佳实践。下面4个类存在继承和包含关系

public class QrScene {
    private String remark;
}
public class QrSceneInteger extends QrScene {
    private Integer scene_id;
}
public class QrSceneString extends QrScene {
    private String scene_str;
}
public class QrSceneWrapper implements Serializable {
    private static final long serialVersionUID = 1L;
    private QrScene scene;
}

// 通过传入参数创建不同数据类型的对象并返回
    private <T> QrSceneWrapper getQrSceneWrapper(T data){
        QrSceneWrapper qrSceneWrapper = null;
        if(data instanceof String){
            qrSceneWrapper = new QrSceneWrapper();
            QrSceneString qrSceneString = new QrSceneString();
            qrSceneString.setScene_str((String) data);
            qrSceneWrapper.setScene(qrSceneString);
        }else if(data instanceof Integer){
            qrSceneWrapper = new QrSceneWrapper();
            QrSceneInteger qrSceneInteger = new QrSceneInteger();
            qrSceneInteger.setScene_id((Integer) data);
            qrSceneWrapper.setScene(qrSceneInteger);
        }
        if(qrSceneWrapper != null) return qrSceneWrapper;
        throw new BusinessException("用于兑换二维码的场景值的ticket只支持两个类型:Integer,String");
    }

有个要求是不可让一个对象中同时出现属性 scene_id 和 scene_str
求方法 getQrSceneWrapper 的最佳实践。

阅读 2.2k
avatarAI BotBETA
### 最佳实践

在你的案例中,你已经通过继承的方式区分了不同类型的二维码场景(`QrSceneInteger` 和 `QrSceneString`),并使用了一个包装类 `QrSceneWrapper` 来统一处理这些不同类型的场景。然而,你的 `getQrSceneWrapper` 方法中使用了类型检查和强制转换,这通常不是最佳实践,因为它违反了开闭原则(对扩展开放,对修改关闭)。

#### 推荐的最佳实践:

1. **使用工厂模式**:
   创建一个工厂类来根据输入参数生成相应的 `QrScene` 子类实例。这样可以避免在 `getQrSceneWrapper` 方法中进行类型检查和强制转换。

2. **使用多态**:
   让 `QrScene` 类或其子类具有一个统一的方法来获取场景值(无论是 `Integer` 还是 `String`),这样 `QrSceneWrapper` 就不需要关心具体是哪种类型的 `QrScene`。

#### 示例代码:

// 工厂类
public class QrSceneFactory {

public static QrScene createQrScene(Object data) {
    if (data instanceof String) {
        QrSceneString qrSceneString = new QrSceneString();
        qrSceneString.setScene_str((String) data);
        return qrSceneString;
    } else if (data instanceof Integer) {
        QrSceneInteger qrSceneInteger = new QrSceneInteger();
        qrSceneInteger.setScene_id((Integer) data);
        return qrSceneInteger;
    } else {
        throw new BusinessException("用于兑换二维码的场景值的ticket只支持两个类型:Integer,String");
    }
}

}

// 修改后的 getQrSceneWrapper 方法
private QrSceneWrapper getQrSceneWrapper(Object data) {

QrScene scene = QrSceneFactory.createQrScene(data);
QrSceneWrapper qrSceneWrapper = new QrSceneWrapper();
qrSceneWrapper.setScene(scene);
return qrSceneWrapper;

}


通过这种方式,你可以将类型检查和对象创建的逻辑封装在工厂类中,使 `getQrSceneWrapper` 方法更加简洁和易于维护。同时,这也使得未来添加新的 `QrScene` 子类变得更加容易,只需在工厂类中添加相应的逻辑即可,无需修改 `getQrSceneWrapper` 方法。
2 个回答

用策略模式加工厂模式

// 基础类
public class QrScene {
    private String remark;
}

// 子类
public class QrSceneInteger extends QrScene {
    private Integer scene_id;
}

public class QrSceneString extends QrScene {
    private String scene_str;
}

// 包装类
public class QrSceneWrapper implements Serializable {
    private static final long serialVersionUID = 1L;
    private QrScene scene;

    public QrScene getScene() {
        return scene;
    }

    public void setScene(QrScene scene) {
        this.scene = scene;
    }
}

// 策略接口
public interface QrSceneStrategy<T> {
    QrScene createQrScene(T data);
}

// String策略实现
public class QrSceneStringStrategy implements QrSceneStrategy<String> {
    @Override
    public QrScene createQrScene(String data) {
        QrSceneString qrSceneString = new QrSceneString();
        qrSceneString.setScene_str(data);
        return qrSceneString;
    }
}

// Integer策略实现
public class QrSceneIntegerStrategy implements QrSceneStrategy<Integer> {
    @Override
    public QrScene createQrScene(Integer data) {
        QrSceneInteger qrSceneInteger = new QrSceneInteger();
        qrSceneInteger.setScene_id(data);
        return qrSceneInteger;
    }
}

// 工厂类
public class QrSceneFactory {
    private final Map<Class<?>, QrSceneStrategy<?>> strategies = new HashMap<>();

    public QrSceneFactory() {
        strategies.put(String.class, new QrSceneStringStrategy());
        strategies.put(Integer.class, new QrSceneIntegerStrategy());
    }

    @SuppressWarnings("unchecked")
    public <T> QrSceneWrapper createQrSceneWrapper(T data) {
        QrSceneStrategy<T> strategy = (QrSceneStrategy<T>) strategies.get(data.getClass());
        if (strategy == null) {
            throw new BusinessException("用于兑换二维码的场景值的ticket只支持两个类型:Integer,String");
        }
        QrSceneWrapper qrSceneWrapper = new QrSceneWrapper();
        qrSceneWrapper.setScene(strategy.createQrScene(data));
        return qrSceneWrapper;
    }
}

import java.io.Serializable;

class QrScene {
    private final String remark;

    public QrScene(String remark) {
        this.remark = remark;
    }
}

class QrSceneInteger extends QrScene {
    private final Integer scene_id;

    public QrSceneInteger(String remark, Integer scene_id) {
        super(remark);
        this.scene_id = scene_id;
    }
}

class QrSceneString extends QrScene {
    private final String scene_str;

    public QrSceneString(String remark, String scene_str) {
        super(remark);
        this.scene_str = scene_str;
    }
}

class QrSceneWrapper implements Serializable {
    private static final long serialVersionUID = 1L;
    private final QrScene scene;

    public QrSceneWrapper(QrScene scene) {
        this.scene = scene;
    }
}

public class Main {
    public static QrSceneWrapper createQrSceneWrapper(String data) {
        return new QrSceneWrapper(new QrSceneString("remark", data));
    }

    public static QrSceneWrapper createQrSceneWrapper(Integer data) {
        return new QrSceneWrapper(new QrSceneInteger("remark", data));
    }

    public static void main(String[] args) {
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏