我们在定义接口的时候,命名要通用, 不能包含和具体实现相关的字眼,和特定实现有关的方法不要放在接口中
public class AliyunImageStore {
//...省略属性、构造函数等...
public void createBucketIfNotExisting(String bucketName) {
// ...创建bucket代码逻辑...
// ...失败会抛出异常..
}
public String generateAccessToken() {
// ...根据accesskey/secrectkey等生成access token
}
public String uploadToAliyun(Image image, String bucketName, String accessToken) {
//...上传图片到阿里云...
//...返回图片存储在阿里云上的地址(url)...
}
public Image downloadFromAliyun(String url, String accessToken) {
//...从阿里云下载图片...
}
}
// AliyunImageStore类的使用举例
public class ImageProcessingJob {
private static final String BUCKET_NAME = "ai_images_bucket";
//...省略其他无关代码...
public void process() {
Image image = ...; //处理图片,并封装为Image对象
AliyunImageStore imageStore = new AliyunImageStore(/*省略参数*/);
imageStore.createBucketIfNotExisting(BUCKET_NAME);
String accessToken = imageStore.generateAccessToken();
imagestore.uploadToAliyun(image, BUCKET_NAME, accessToken);
}
}}
上面例子,如果我们把实现类换成私有云,就不好处理修改了
AliyunImageStore 这个名字不好,带有 Aliyun ,函数实现不能暴露细节
generateAccessToken 私有云没有token ,这个要修改业务流程,
createBucketIfNotExisting 这一段处理不该暴露 封装具体的实现细节
我们替换下实现
public interface ImageStore {
String upload(Image image, String bucketName);
Image download(String url);
}
对应使用者来说,他只需要知道 upload 和download 就好了,
public void process() {
Image image = ...;//处理图片,并封装为Image对象
ImageStore imageStore = new PrivateImageStore(...);
imagestore.upload(image, BUCKET_NAME)
; }
使用时,需要new具体的实现类,
这一点 如果替换实现类,还需要修改多处引用代码,可以重构掉
比如,借助 spring bean 发现功能
交由Spring容器管理此实现类,如果需要修改,修改此处代码重启即可
@Bean public ImageStore getImageStore() {
return new PrivateImageStore(/*省略构造函数*/);
}
或者使用简单工厂+反射实现