我们在定义接口的时候,命名要通用, 不能包含和具体实现相关的字眼,和特定实现有关的方法不要放在接口中
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(/*省略构造函数*/);}
或者使用简单工厂+反射实现