面向对象思维举例
我们经常有对图片进行处理的需求。本文就从最简单的要求到比较复杂的要求描述面向对象的抽象方式
下面假设调用方按照以下的协议进行调用:
ImageManager -src image_src_path -resize 100x200 -rorate 90 -...
-src表示来源图片
-resize 表示缩放
....
需求1:对图片进行缩放后存到指定的位置
解决方法:
很简单,只需要两个功能:缩放和存储图片的功能
代码1:
public void processImage(String imageSrc,int newWidth, int newHeight,String imageDest){
MyImage image = ... //读取来源图片
MyImage newImg = resize(image,newWidth,newHeight);
saveImage(newImage,imageDest);
//剩下的是释放资源的操作
}
private MyImage resize(MyImage image, int newWidth, int newHeigth){
//缩放的代码
}
private void saveImage(MyImage image, String destpath){
//存储的代码
}
需求2:对图片按照固定的顺序(缩放、旋转、剪切、锐化等,即命令行中resize 必须在 rorate之前)处理后保存新的图片
解决方法:
依然简单,按照代码1的逻辑添加新处理图片的方法即可
代码:
public void processImage(ImageInfo info){// 这里的info存放的是操作所需要的信息,比如旋转的角度等
MyImage image = ... //读取来源图片
MyImage newImg = resize(image,newWidth,newHeight);// 缩放
newImg = rorate(...);//旋转
newImg = cut(...);//剪切
newImg = sharpend(...)//锐化
//释放资源
}
需求3: 根据调用放输入命令的前后顺序对图片进行处理.
比如,输入-resize 100x200 -rorate 90 :缩放-> 旋转
输入-rorate 90 -resize 100x200 -cut 200x200 :旋转->缩放->剪切
解决方法:
最直接的方法: 先获取操作的前后顺序,然后if-else搞定
代码3.1:
public void processImage(ImageInfo info){// 这里的info存放的是操作所需要的信息,比如旋转的角度等
MyImage image = ... //读取来源图片
List<String> operateList = ...// 获取操作的先后顺序,放在数组中
for(String op : operateList){
image = process(op, ...);
}
//释放资源
}
public MyImage process(String op, ...){
if(缩放){
return resize(。。。)
}
if(旋转){
return rorate(..);
}
...
}
需求4:在需求3的基础上另外再加上10个操作。
解决方法4.1 :
在 public MyImage process(String op, ...)中添加新的if-else进行处理。
优点:很直观,很容易理解。
缺点:1:if太多
2:process方法过长
3:每添加一个一个新的操作就要修改原来的逻辑代码process(),这是非常危险的
解决方法4.2:
将对图片的操作抽象为一个接口:
interface ImageOperation{
operate(ImageInfo info);
}
class RorateOperation implements ImageOperation{
...
}
...
static{
map.put("rorate",new RorateOperation());
...
}
public void processImage(ImageInfo info){// 这里的info存放的是操作所需要的信息,比如旋转的角度等
MyImage image = ... //读取来源图片
List<String> operateList = ...// 获取操作的先后顺序,放在数组中
for(String op : operateList){
Operator p = getOperator(op);
p.operate(p);
}
//释放资源
}
public ImageOperation getOperator(String op){
return map.get(op);
}
好处:避免了过长的process();逻辑特别清晰;极大程度上支持开-闭原则
缺点:将会创造比较多操作类,换来的好处就是每个类(算法)都特别精炼。