面向对象的六大基本原则
来源:互联网 发布:玉虚男捏脸数据 编辑:程序博客网 时间:2024/06/05 11:12
一.单一职责原则(Single Responsibility Principle)缩写SRP
就一个类而言,应该仅有一个引起它的变化原因(换句话说,也就是一个类最好制作一件事(这个一件事的定义比较难定义,看个人))
例子:imageLoader
最开始的imageLoader里面有 图片加载逻辑 和 处理图片缓存的逻辑 ,这在我们看来就不符合SRP原则,所以要分开,分成图片加载逻辑(ImageLoader),和缓存部分(ImageCache)
二.开闭原则(Open Close Principle)缩写是OCP
开闭原则定义是:软件中的对象(类,模块,函数等)应该对于扩展是开放的,但是对于修改是封闭的。(换句话说,让软件需要变化时,我们应该尽量通过扩展的方式来实现变化,而不是通过修改已有的代码来实现)
例子:ImageLoader 需要加个缓存机制(本地或者网络)
问题:怎么让缓存机制变得可扩展,可以让用户随便改
public class ImageLoader { //图片缓存 ImageCache mImageCache = new MemoryCache(); .....//一些代码 //注入缓存实现 public void setmImageCache(ImageCache cache){ mImageCache = cache; } public void display(String imageUrl,ImageView imageView){ //如果图片不是null就设置图片 //如果图片是null就去获取 //提交到线程池去下载 submitLoadRequest(imageUrl,imageView); } public void submitLoadRequest(final String imageUrl ,final ImageView imageView){ ....//一些代码 @Override public void run () { ...//一些代码 mImageCache.put(imageUrl, imageView); } }}
上面是最终代码,可以看出解决了问题,用什么缓存机制由我们自己说了算通过setImageCache(这里默认用了Memory)
public interface ImageCache{ public Bitmap get(String url); public void put(String url,Bitmap bmp);}
然后不管是内存缓存还是本地缓存,或者两者都有都继承这个就行,然后用户自己定制就可以了
比如
MemoryCache,DiskCache,DoubleCache都是实现接口ImageCache,所以可以这么干
imageloader.setImageCache(new MemoryCache())
imageloader.setImageCache(new DiskCache())
imageloader.setImageCache(new DoubleCache())
三.里氏替换原则(Liskov subsitution Princile)简称LSP
所有引用基类的地方必须能透明地使用其子类的对象。(说白了就是只要父类能出现的地方子类就能出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类,但是反过来就不行,有子类的地方,父类未必就能适应,最后其实就是抽象)
MemoryCache,DiskCache,DoubleCache都是实现接口ImageCache,所以可以这么干
imageloader.setImageCache(new MemoryCache())
imageloader.setImageCache(new DiskCache())
imageloader.setImageCache(new DoubleCache())
这个就是用到了里氏替换原则。
四.依赖倒置原则(Dependence Inversion Principle)
依赖倒置原则有以下几个关键点。
(1)高层模块(调用端)不应该依赖低层模块(具体实现类),两者都应该依赖抽象
(2)抽象(接口或者抽象类)不应该依赖细节
(3)细节(实现接口或继承抽象类而产生的类就是细节)应该依赖抽象
在Java语言中的表现就是:模块间的依赖通过抽象发生,实现类之间不发生直接依赖关系,其依赖关系是通过接口或抽象类产生的。
例如上面的例子:
public class ImageLoader { //图片缓存 ImageCache mImageCache = new MemoryCache();.....}
可以看出ImageLoader依赖的是接口ImageCache,这个就是对的
如果是下面这样那就是依赖细节了
public class ImageLoader { //图片缓存 MemoryCache memoryCache = new MemoryCache();.....//}
这样就不行,不方便扩展
ImageCache mImageCache = new MemoryCache();
这样写的话,如果有需求要改的话只需要实现ImageCache类或者继承其他已有的ImageCache子类完成相应的缓存功能。这样就保证了高扩展性!!!
五.接口隔离原则(Interface Segregation Principles)简称ISP
其实就是客户端不应该依赖他不需要的接口(也可以理解为:类间的依赖关系应该建立在最小的接口上)
public void put(String url,Bitmap bmp){ try{ FileOutputStream fileOutputStream = null; fileOutputStream = new FileOutputStream(cacheDir + url); bmp.compress(Bitmap.CompressFormat.PNG, 100 , fileOutputStream); }catch (FileNotFoundException e){ e.printStackTrace(); }finally { if(fileOutputStream != null){ try{ fileOutputStream.close(); }catch{ e.printStackTrace(); } } }}
Try catch各种嵌套,这样看起来很不好看影响代码阅读性
<span style="font-family: Arial, Helvetica, sans-serif;">public final class CloseUtils{</span>
private CloseUtils(){} /** * 关闭Closeable对象 * @param closeable * */ public static void closeQuitely(Closeable closeable){ if(null != closeable){ try{ closeable.close(); }catch (IOException e){ e.printStackTrace(); } } }}public void put(String url ,Bitmap bmp){ FileOutputStream fileOutputStream = null; try{ FileOutputStream fileOutputStream = null; fileOutputStream = new FileOutputStream(cacheDir + url); bmp.compress(Bitmap.CompressFormat.PNG, 100 , fileOutputStream); }catch (FileNotFoundException e){ e.printStackTrace(); }finally { CloseUtils.closeQuitely(fileOutputStream); }}
这个方法的基本原理就是依赖于Closeable抽象而不是具体实现,并且建立在最小化依赖原则的基础上,他只需要知道这个对象是否可关闭,其他的一概不关心
六.迪米特原则(Law of Demeter)缩写LOD
一个对象应该对其他对象有最少的了解
例子:在北京租房
/** * 房间 * */public class Room{ public Room(float area ,float price){ this.area = area; this.price = price; } @Override public void toString(){ return "Roomasdsad" }}/** * 中介 * */public class Mediator{ List<Room> mRooms = new ArrayList<>(Room)(); public Mediator(){ for(int i =0;i<5;i++){ mRooms.add(new Room(14+i,(14+i)*150)); } } public List<Room> getAllRooms(){ return mRooms; }} /** * 租户 * */public void Tenant{ public float roomArea; public float roomPrice; public static final float diffPrice = 100.0001f public static final float diffArea = 0.00001f; public void rentRoom(Mediator mediator){ List<Room> rooms = mediator.getAllRooms(); for(Room room : rooms){ if(isSuitable(room)){ System.out.println("租到房间啦 !" +room); break; } } } }
可以看出Tenant不仅依赖Mediator类,还需要频繁地与Room类打交道
,租户类的要求只是通过中介找到一间适合自己的房间罢了,如果把这些检测条件都放在Tenant类中,那么中介类的功能就被弱化了,而导致Tenant与Room的耦合较高
(会导致当Room变化时Tenant也必须跟着变化,Tenant又与Mediator耦合)
/** * 房间 * */public class Room{ public Room(float area ,float price){ this.area = area; this.price = price; } @Override public void toString(){ return "Roomasdsad" }}/** * 中介 * */public class Mediator{ List<Room> mRooms = new ArrayList<>(Room)(); public Mediator(){ for(int i =0;i<5;i++){ mRooms.add(new Room(14+i,(14+i)*150)); } } public void rentOut(float area,float price){ for(Room room : rooms){ if(isSuitable(area ,price ,room)){ System.out.println("租到房间啦 !" +room); break; } } private boolean isSuitable(float area , float price,Room room){ return Math.abs(room.price - price )<Tenant.diffPrice &&Math.abs(room.area -area ) - Tenant.diffprice; } }} /** * 租户 * */public void Tenant{ public float roomArea; public float roomPrice; public static final float diffPrice=100.0001f public static final float diffArea=0.00001f; public void rentRoom(Mediator mediator){ System.out.println("租到房了"+mediator.rentOut(roomArea,roomPrice)) } }
这里只是将对于room的判定操作转移到了Mediator类中,这本应该是Mediator的职责
- 面向对象的六大基本原则
- 面向对象的六大基本原则
- 面向对象六大基本原则
- 面向对象六大基本原则
- 面向对象六大基本原则
- 面向对象设计的六大基本原则
- java面向对象程序设计的六大基本原则
- 面向对象设计的六大基本原则
- 面向对象设计六大基本原则
- 走向灵活的软件之路--面向对象六大基本原则
- (Java)面向对象编程六大基本原则
- 面向对象的基本原则:
- 面向对象的基本原则
- 面向对象的基本原则
- 面向对象的基本原则
- 面向对象的基本原则
- 面向对象的基本原则
- 面向对象设计的六大基本原则(设计模式6大原则)
- 在苹果MAC机上安装Windows7系统-解决键盘和鼠标失效的问题
- Remove Duplicates from Sorted Array
- 《疯狂Java讲义》——控制线程
- hrbust/哈理工oj 1981 【tab缩进、水题】
- HDU 4902 Nice boat(线段树)
- 面向对象的六大基本原则
- 单例模式
- BZOJ 4200 NOI 2015 小园丁与老司机
- 判断是否为素数
- 多维数组元素的下标引用于指针访问
- 算法:经典数据结构题
- Coordinates
- 推荐几个好玩又有难度的编程网站
- HUST 1601 Shepherd