有个案例我不知道是否对应哪个设计模式,求一个最佳实践。下面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 的最佳实践。
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) {
}
}
// 基础类
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;
}
}
### 最佳实践
在你的案例中,你已经通过继承的方式区分了不同类型的二维码场景(`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` 方法。
问题内容: 在厌倦了c3p0的恒定锁定之后,我将转向BoneCP作为数据库的备用连接池。我有一个服务器应用程序,每分钟处理大约7,000个项目,需要将这些项目记录到我们的MySQL数据库中。我目前有100个工作线程,并按如下方式设置了我的池: 这些应用程序是否接受这些设置?我问是因为运行一两分钟后,在尝试调用池时出现BoneCP异常。谢谢您的帮助。 这是我在工作线程中用于db调用的代码,它不会在网
问题内容: 有时,当我看到自己的日志记录代码时,我想知道自己是否做对了。可能没有确切的答案,但是我有以下担忧: 图书馆课 我有几个库类可能记录一些消息。致命错误被报告为例外。当前,我的类中有一个静态记录器实例,其类名称为记录名称。(Log4j的:) 这是正确的方法吗?也许该库类的用户不需要我的实现中的任何消息,或者想要将它们重定向到应用程序特定的日志。我是否应该允许用户从“外部世界”设置记录器?您
这里有些给使用和编写 Ansible playbook 的贴士. 你能在我们的 ansible-example repository.找到展示这些最佳实践的 playbook 样例.(注意: 这些示例用的也许不是最新版的中所有特性,但它们仍旧是极佳的参考.) Topics 最佳实践 接下来的章节将向你展示一种组织 playbook 内容方式. 你对 Ansible 的使用应该符合你的需求而不是我们
处理后台任务与常规调用方法有很大的不同。本指南旨在帮助让您的后台任务平稳有效地运行。本文基于 这篇博客文章。 使任务参数小而简单 方法(任务)在调用之前会被序列化。使用 TypeConverter 类将参数转换为 JSON 字符串。如果您有复杂的实体和 / 或大对象; 包括数组,最好将它们放入数据库,然后只将其标识 (id) 传递给后台任务。 错误例子: public void Method(En
VR设计 VR设计不同于平面体验设计。作为一种新的媒介,有新的最佳实践需要遵循,特别是保持用户的舒适性和存在性。这在如下指南中已经写得很透彻了: Oculus VR最佳实践 Leap Motion VR最佳实践指南 一些值得注意的事情: 公共的金科玉律是永远不要意外地把相机控制权从用户手中剥夺。 单位(比如对于位置)应该考虑使用米(m)。这是因为WebVR API以米为单位返回姿势数据,进而传送给
本章文档将阐述一些使用herosphp开发一些常用模块的一些比较好的实践。 未完待续。。。
适当的使用vuex 能不用就不用。 能用就用。 不要为了使用而使用,一个小方法里面有5个设计模式。 不要过度使用CSS框架 因为CSS框架一般会大幅度增加文件体积。 例如 bootstrap, ele.me前端框架。 这个在低端安卓机上影响显著。 使用CDN来存放js, css, 和图片文件。 灵活使用第三方Vue 插件 例如: 轮播图, 表单验证等等。这些轮子都是现成的。 前端逻辑务必简单 能在
这是 Martin Zinkevich (Google) 在 NIPS 2016 Workshop 分享的谷歌机器学习最佳实践翻译版,PDF 全文见 Rules of Machine Learning: Best Practices for ML Engineering。 机器学习产品所要面对的难题是工程问题(而不是 ML 算法),所以在做机器学习时要遵循跟其他产品类似的工程原则。 术语 实例(