程序设计6大原则

程序设计六大原则

2017年12月24日 22:57:20 LBJFxd 阅读数:7603编程

 版权声明:本文为博主原创文章,转载请注明出处! https://blog.csdn.net/fanxudonggreat/article/details/78888267缓存

1.单一职责网络

简单来讲单一职责就是一个类只负责一个功能。更加具体的说就是对一个类而言,应该是一组相关性很高的函数、数据的封装,是高内聚低耦合的,对外界而言应该仅有一个引发它变化的缘由。架构

单一职责在项目中的使用:框架

1.项目中的新手引导变量的管理能够统一在各自的Modle中用单独的类来管理ide

2.MVP模式P层生命周期与V层生命周期的同步能够用单独的包装类来实现,函数

3.各类基础框架功能的定义,例如:图片的加载、缓存、显示等都应该在各自的类中去作。this

下面以一个图片加载库的实现为例:成功加载一张图片可分为:请求、缓存、加载三个步骤,那咱们就按照单一职责去建立三个类分别实现这三个功能url

/**
 * 图片显示
 */
public class ImageLoad {

    public void displayImage(String url, ImageView imageView) {

    }

}

/**
 * 图片缓存
 */
public class ImageCache {

    public void put(String url,Bitmap bitmap){

    }

    public Bitmap get(String url){

    }

}

/**
 * 图片加载
 */
public class ImageRequest {

    public Bitmap downloadImage(String url){

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

上面的例子:ImageLoad只负责显示图片,ImageRequest负责从网络下载图片,ImageCache负责处理图片缓存逻辑,这样设计各自的类职责至关单一,假如咱们须要修改缓存的逻辑,咱们只须要修改ImageCache的逻辑,若项目升级咱们须要升级网络请求库,那涉及到图片部分咱们也只须要修改ImageRequest类便可。总之:单一职责所要表达的用意就是”单一”二字,可是如何划分一个类、甚至是一个函数的职责,这就须要每个开发者本身去设计。spa

2.开闭原则

开闭原则的英文全称是Open Close Principle缩写即OCP。开闭原则的定义是:软件中的对象(类、模块、函数等)应该对于扩展是开放的,可是对于修改是封闭的。在软件的生命周期内,由于变化、升级和维护等缘由须要对软件的原有代码进行修改时,可能会将错误的代码引入,从而破坏原有系统。所以当软件需求发生变化时,咱们应该尽可能经过扩展的方式 来实现变化,而不是经过修改已有的代码。

开闭原则在项目中的使用:

1.基类与子类,子类能够继承父类并扩展父类的功能

2.接口与实现类,接口定义功能,实现类按照各自的需求实现

继续以上面的图片加载框架为例:上面咱们定义了三个类:ImageLoad,ImageRequest,ImageCache分别来作显示、加载、缓存这三件事,很简单的知足了单一职责的原则,可是当咱们不一样状况下须要执行不一样的缓存策略时是否是每次又要去修改ImageCache这个类?这是否是跟咱们的开闭原则相违背?ImageRequest一样如此。所以咱们须要保证在添加新的缓存策略时不须要修改原来的类,只须要在此基础上扩展就能够了,这样就能够避免修改原来的类引发的未知的错误。

/**
 * 图片显示
 */
public class ImageLoad {

    public void displayImage(String url, ImageView imageView) {

    }

}

/**
 * 图片缓存
 */
public interface ImageCache {

    public void put(String url,Bitmap bitmap);

    public Bitmap get(String url);

}

/**
 * 图片加载
 */
public interface ImageRequest {

    public Bitmap downloadImage(String url);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

注意:咱们只是将ImageCache类和ImageRequest类改为了接口,这样的好处就是咱们须要添加新的缓存策略时只须要实现ImageCache接口,ImageRequest一样如此。下面咱们实现内存缓存和SD卡缓存

/**
 * 内存缓存
 */
public class MemoryCache implements ImageCache {

    @Override
    public void put(String url, Bitmap bitmap) {

    }

    @Override
    public Bitmap get(String url) {
        return null;
    }
}

/**
 * SD卡缓存
 */
public class DiskCache implements ImageCache {

    @Override
    public void put(String url, Bitmap bitmap) {

    }

    @Override
    public Bitmap get(String url) {
        return null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

而后在咱们的ImageLoad中能够动态注入ImageCahce实现:

/**
 * 图片显示
 */
public class ImageLoad {

    private ImageCache mCache = new MemoryCache();//默认缓存策略为内存缓存

    /**
     * 缓存策略注入
     */
    public void setImageCache(ImageCache imageCache) {
        this.mCache = imageCache;
    }

    public void displayImage(String url, ImageView imageView) {

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在上面的例子中,经过setImageCache方法开发者能够对ImageLoad注入不一样的缓存实现,这使得ImageLoad更加简单、健壮、扩展性、灵活性更高,同时也使得ImageCache的添加简单高效(只须要实现ImageCache接口而后经过setImageCache注入),而且这些扩展不会不会致使ImageLoad类修改。这正是开闭原则的核心思想:对扩展开发,对修改封闭。

3.里氏替换原则

里氏替换原则的定义:若是对每个类型为S的对象O1,都有类型为T的对象O2,程序P在全部的对象O1都带换成O2时,程序P的行为没有发生变化,那么类型S是类型T的子类型换言之就是全部引用基类的地方必须能透明的使用其子类的对象。更通俗的讲就是只要父类出现的地方子类就能够出现,并且替换为子类也不会产生任何的错误或者异常。

里氏替换原则的核心是抽象,而抽象又依赖于继承这个特性,在OOP当中,继承的优缺点都至关明显。

优势:

1.代码重用,减小建立类的成本,每一个子类都拥有父类的方法和属性

2.子类与父类基本类似,但又与父类有所区别

3.提升代码的可扩展性

缺点:

1.继承是侵入性的,只要继承就必须拥有父类的方法和属性

2.可能形成子类代码冗余,灵活性下降,由于子类必须拥有父类的属性和方法

在上面的例子中,咱们经过ImageCache创建起了一套缓存的规范,在经过setImageCache注入不一样的具体实现,保证了系统的扩展性和灵活性。所以开闭原则和里氏替换原则每每是生死相依,如影随行的,经过里氏替换原则来达到对扩展开放,对修改关闭的效果。

4.依赖倒置原则

依赖倒置原则指定了一种特定的解耦形式,使得高层次的模块不依赖与低层次模块的实现细节的目的,依赖模块被颠倒了。依赖倒置原则有如下几个关键点:

1.高层模块不该该依赖于低层模块,二者都应该依赖其抽象

2.抽象不该该依赖于细节

3.细节应该依赖于抽象

在Java语言中,抽象就是指接口或者抽象类,两者都是不可以被直接实例化的:细节就是实现类,实现接口或者抽象类而产生的类就是细节,其特色就是能够直接被实例化,也就是可使用关键字new产生一个对象。高层模块就是指调用端,底层模块就是指具体的实现类。依赖倒置原则在Java语言中的表现就是:模块间的依赖经过抽象产生,实现类之间不发生直接的依赖关系,其依赖关系是经过接口或者抽象类产生的。使用一句话归纳就是:面向接口编程或者说是面向抽象编程。

若是类与类直接依赖细节,那么这几个类之间就有直接的耦合,当具体的需求发生变化是,意味着同时修改依赖者的代码。在上面图片加载的例子中,ImageLoad这个类依赖于ImageCache这个接口,而具体的实现能够经过setImageCache注入,这样当Cache策略须要升级时,只须要实现ImageCache接口,而后经过setImageCache注入到ImageLoad中。这样就保证了细节与依赖的隔离。

5.接口隔离原则

接口隔离原则的定义是:客户端不该该依赖于他不须要的接口。另外一种定义是:类之间的依赖关系应该创建在最小的接口上。接口隔离原则将很是庞大,臃肿的接口拆分红更小的和更具体的接口,这样客户端将会值须要知道它们感兴趣的方法。接口隔离原则的目的是系统解开耦合,从而容易重构、更改和部署。

在上面的IamgeLoad例子中,ImageCache指向ImageLoad提供了get和put方法,其余一律无论,这使得具体的缓存策略实现对ImageLoad隐藏,这就是使用最小化接口隔离了实现类的细节,也促使咱们将更加庞大的接口拆分到更细粒度的接口当中,这一样使得咱们的系统具备更低的耦合性、更高的灵活性。

6.迪米特原则

迪米特原则:一个对象应该对其余对象有最少的了解,通俗的讲,一个类应该对本身须要耦合或调用的类知道的最少,类的内部如何实现与调用者或者依赖者没有关系,调用者或者依赖者只须要知道他须要的方法便可,其余的一律无论。类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另外一个类的影响也越大。

在上面的图片加载框架设计中,咱们的IamgeLoad只依赖于ImageCache的get和put方法,对其内部实现细节一无所知,即便经过setImageCache改变注入的对象时,ImageLoad也是对其内部实现细节不关心的,ImageLoad只关心ImageCache提供的get和put方法。这样使得系统具备更加低的耦合性和更好的扩展性。

小结:

在应用开发过程当中,最难的不是完成应用的开发工做,而是在后续的升级、维护过程当中让应用系统可以拥抱变化。拥抱变化也意味着在知足需求并且不破坏系统稳定的前提下保持高可扩展性、高内聚、低耦合,在经历了各版本的变动以后依然保持着清晰、灵活、稳定的系统架构。

相关文章
相关标签/搜索