# 单一职责原则

## 计算器实例

package Recursion;

/**
* Created by lirui on 2018/12/6.
*/
public class JiSuanQi {
int a;
int b;

public JiSuanQi(int a, int b) {
this.a = a;
this.b = b;
}

//加法
public int add(int a, int b) {
return a + b;
}

//减法
public int sub(int a, int b) {
return a - b;
}
}


public class AddJiSuanQi extends  JiSuanQi {
public AddJiSuanQi(int a, int b) {
super(a, b);
}
//加法
public int add(int a, int b) {
return a + b;
}
}

1. 减法类SubJiSuanQi
public class SubJiSuanQi extends JiSuanQi {
public SubJiSuanQi(int a, int b) {
super(a, b);
}
//减法
public int add(int a, int b) {
return a - b;
}
}



# 开放封闭原则(OCP)

## 开放封闭原则示例（书店售书）

1. 类图

2. 代码实现

/**
* 书籍接口
* Created by lirui on 2018/12/6.
*/
public interface IBook {
//书籍名称
public String getName();
//书籍售价
public int getPrice();
//书籍作者
public String getAuthor();
}

package Book;

/**
* Created by lirui on 2018/12/6.
*/
public class NovelBook implements IBook {
//书籍名称
private String name;
//书籍的价格
private int price;
//通过构造函数传递书籍数据
private String author;

public NovelBook(String name, int price, String author) {
this.name = name;
this.price = price;
this.author = author;
}

@Override
public String getName() {
return this.name;
}

@Override
public int getPrice() {
return this.price;
}

@Override
public String getAuthor() {
return this.author;
}
}


package Book;

import java.text.NumberFormat;
import java.util.ArrayList;

/**
* Created by lirui on 2018/12/6.
*/
public class BookStore {
private final static ArrayList<IBook> bookList=new ArrayList<>();
static {
}
//模拟书店买书
public static void main(String[] args) {
NumberFormat format=NumberFormat.getCurrencyInstance();
format.setMaximumFractionDigits(2);
System.out.println("-=-=-=-=-=-=-=-=书店卖出书籍记录-=-=-=--=-=-=-=-");
for (IBook book:bookList){
System.out.println("书籍名称："+book.getName()+"\t书籍作者："+book.getAuthor()+"\t书籍价格:"+format.format(book.getPrice()/100.0)+"元");
}
}
}

-=-=-=-=-=-=-=-=书店卖出书籍记录-=-=-=--=-=-=-=-



1. 第一个办法：

1. 第二个办法：

1. 第三个办法：

/**
* 书籍打折类
* Created by lirui on 2018/12/6.
*/
public class OffNovelBook extends NovelBook {
public OffNovelBook(String name, int price, String author) {
super(name, price, author);
}
//覆写销售价格
@Override
public int getPrice(){
//原价
int prePrice=super.getPrice();
int offPrice=0;
if (prePrice>=200){
offPrice=prePrice*80/100;
}else{
offPrice=prePrice*90/100;
}return offPrice;
}
}


/**
* Created by lirui on 2018/12/6.
*/
public class BookStore {
private final static ArrayList<IBook> bookList=new ArrayList<>();
static {
}
//模拟书店买书
public static void main(String[] args) {
NumberFormat format=NumberFormat.getCurrencyInstance();
format.setMaximumFractionDigits(2);
System.out.println("-=-=-=-=-=-=-=-=书店卖出书籍记录-=-=-=--=-=-=-=-");
for (IBook book:bookList){
System.out.println("书籍名称："+book.getName()+"\t书籍作者："+book.getAuthor()+"\t书籍价格:"+format.format(book.getPrice()/100.0)+"元");
}
}
}

-=-=-=-=-=-=-=-=书店卖出书籍记录-=-=-=--=-=-=-=-



1. 扩展接口再扩展实现：
书店又增加了计算机类书籍，该类书还有一个独特特性：面向的是什么领域

/**
* 计算机书籍接口
* Created by lirui on 2018/12/6.
*/
public interface IComputerBook extends IBook{
//计算机书籍范围
public String getScope();
}

**
* 计算机书籍类
* Created by lirui on 2018/12/6.
*/
public class ComputerBook implements IComputerBook {
private String name;
private int price;
private String author;
private String scope;
public ComputerBook(String name,int price,String author,String scope){
this.name=name;
this.price=price;
this.author=author;
this.scope=scope;
}
@Override
public String getName() {
return this.name;
}

@Override
public int getPrice() {
return this.price;
}

@Override
public String getAuthor() {
return this.author;
}

@Override
public String getScope() {
return this.scope;
}
}

/**
* 书店
* Created by lirui on 2018/12/6.
*/
public class BookStore {
private final static ArrayList<IBook> bookList=new ArrayList<>();
static {
}
//模拟书店买书
public static void main(String[] args) {
NumberFormat format=NumberFormat.getCurrencyInstance();
format.setMaximumFractionDigits(2);
System.out.println("-=-=-=-=-=-=-=-=书店卖出书籍记录-=-=-=--=-=-=-=-");
for (IBook book:bookList){
System.out.println("书籍名称："+book.getName()+"\t书籍作者："+book.getAuthor()+"\t书籍价格:"+format.format(book.getPrice()/100.0)+"元");
}
}

-=-=-=-=-=-=-=-=书店卖出书籍记录-=-=-=--=-=-=-=-



# 里氏替换原则（LSP）

1. 问题描述
一个功能T有类A来完成，后来由于需求的变化，该功能T被分为了T1和T2两部分，这两部分的功能分别有类A的子类：类B和类C来完成。如果功能T1发生了变化，修改类B的同事，有可能引起T2的功能产生故障。

2. 产生原因
在继承关系中，基类的存在是为整个继承的结构设定一系列的规定和约束，让整个结构都按照这个规定和约束来。例如说用一个基类来描述鸟类，根据我们对鸟类的一贯认知，会在基类中通过约定有羽毛属性，有飞翔行为的是鸟类。这样在实现布谷鸟或者杜鹃鸟的时候，它都有基类中规定的属性和行为约束，但是突然有一天boss过来说把企鹅也要加进来，因为企鹅也属于鸟类。此时我们在继承了鸟类这个基类的时候，把羽毛属性和飞翔的行为都改了。此时布谷鸟或者杜鹃鸟就都如企鹅一般没了羽毛，并且不会飞翔了。

3. 解决办法
当使用继承的时候，使用里氏替换原则。当使用继承的时候，尽量不覆盖或重写父类的方法。当扩展父类方法的时候，保证不影响父类功能的前提下扩展。

4. 实例

/**
* 猫
* Created by lirui on 2018/12/6.
*/
public class Cat {
public void say(){
System.out.println("喵喵喵");
}
}


/**
1. 高冷猫
2. Created by lirui on 2018/12/6.
*/
public class SpcCat extends Cat {
@Override
public void say(){
System.out.println("不叫了");
}
}


Liskov于1987年提出了一个关于继承的原则“Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”——“继承必须确保超类所拥有的性质在子类中仍然成立。”也就是说，当一个子类的实例应该能够替换任何其超类的实例时，它们之间才具有is-A关系。

   如果用里氏替换原则来判断一个类的框架是否合理的话，继承和多态是不是就没用了？答案显然是否定的。就上


 总结起来就是：子类实现父类的抽象方法优先，但是不能覆盖父类的抽象方法。但是当子类必须要实现父类的方法的时候，那么就要遵守里氏替换原则中的第三条和第四条。


# 接口隔离原则

1. 问题描述
当一个提供接口的类中对于它的子类来说不是最小的接口，那么它的子类在实现该类的时候就必须要实现一些自己不需要的功能。如此一来，整个系统就会变得臃肿难以维护。

2. 问题由来
当类A通过接口I来依赖B，类C也通过接口I来依赖D，那么对于类A和类C来说，如果接口I不是最小接口，那么类B和类D就必须要实现他们不需要的方法。

3. 解决问题
遵守接口隔离原则，将“胖大”接口I拆分为独立的几个接口，类A和类C分别与他们需要的接口类来建立依赖关系。这样他们依赖的类就不需要实现他们不需要的方法。

4. 实例
场景：某高三学生需要进行一次模拟测试，由于文理科教学内容之别，那么他们考试内容也有区别。假如现在考试的内容有语文，数学，地理，物理这些科目。 作为文科生，他们只考语文，数学，地理；而作为理科生，他们要考语文，数学，物理。用Java来实现这个功能

public interface IExam {

public void chinese();
public void math();
public void physics();
public void geograp();
}


public class ArtsExam implements IExam {
@Override
public void chinese() {
System.out.println("语文");
}

@Override
public void math() {
System.out.println("数学");
}

@Override
public void physics() {

}

@Override
public void geograp() {
System.out.println("地理");
}
}


public class PhyExam implements IExam {
@Override
public void chinese() {
System.out.println("语文");
}

@Override
public void math() {
System.out.println("数学");
}

@Override
public void physics() {
System.out.println("物理");
}

@Override
public void geograp() {

}
}

如此实现的话显然是有问题的，为什么一个类里面会出现空方法这么尴尬的东西。如果现在文理科目不止这四科，增加了生物，历史等等，那是不是出现的空方法就更多了。这时候就需要使用接口隔离原则，让类之间的依赖建立在最小接口的原则上。

1. 用接口隔离原则实现
考试接口基类
public interface IExam {

public void chinese();
public void math();
}


/**
* 文科接口类
* Created by lirui on 2018/12/6.
*/
public interface IArtExam extends IExam {
public void geograp();
}



/**
* 理科接口类
* Created by lirui on 2018/12/6.
*/
public interface IPhyExam extends IExam {
public void physics();
}


public class ArtsExam implements IArtExam {
@Override
public void chinese() {
System.out.println("语文");
}

@Override
public void math() {
System.out.println("数学");
}

@Override
public void geograp() {
System.out.println("地理");
}
}



public class PhyExam implements IPhyExam {
@Override
public void chinese() {
System.out.println("语文");
}

@Override
public void math() {
System.out.println("数学");
}

@Override
public void physics() {
System.out.println("物理");
}
}


# 依赖倒置原则

A.高层次的模块不应该依赖于低层次的模块，他们都应该依赖于抽象。
B.抽象不应该依赖于具体实现，具体实现应该依赖于抽象。

1. 为什么要遵循依赖倒置原则

很多时候我们更改一个需求，发现更改一处地方需要更改多个文件，看见很多的报错我们自己都觉得烦，我们很清醒的意识到这是因为严重的耦合导致的，所以自然要想办法解决这个问题
2. 依赖倒置有什么好处

1. 例子
公司是奇瑞和江淮公司的金牌合作伙伴，现要求开发一套自动驾驶系统，只要汽车上安装该系统就可以实现无人驾驶，该系统可以在奇瑞和江淮车上使用，只要这两个品牌的汽车使用该系统就能实现自动驾驶。

2. 常规写法

/**
* 奇瑞汽车
* Created by lirui on 2018/12/6.
*/
public class QQ {
public  void run(){
System.out.println("奇瑞汽车启动");
}
public void stop(){
System.out.println("奇瑞汽车停止");
}
}


/**
* 江淮汽车
* Created by lirui on 2018/12/6.
*/
public class JAC {
public void run(){
System.out.println("江淮汽车启动");
}
public void stop(){
System.out.println("江淮汽车停止");
}
}

/**
* 自动驾驶系统
* Created by lirui on 2018/12/6.
*/
public class AutoSystem {
private String mType;
private QQ qq;
private JAC jac;
public AutoSystem(String mtype){
this.mType=mtype;
qq=new QQ();
jac=new JAC();
}
public void AutoRun(){
if ("qq".equals(mType)){
qq.run();
}else{
jac.run();
}
}
public void AutoStop(){
if ("qq".equals(mType)){
qq.stop();
}else{
jac.stop();
}
}
}


1. 首先观察江淮和奇瑞两个类

public interface ICar {
public void run();
public void stop();
}

1. 其次来我们看定义

A.高层次的模块不应该依赖于低层次的模块，他们都应该依赖于抽象。
B.抽象不应该依赖于具体实现，具体实现应该依赖于抽象。

/**
* 自动驾驶系统
* Created by lirui on 2018/12/6.
*/
public class AutoSystem {
private ICar iCar;
public AutoSystem(ICar iCar){
this.iCar=iCar;
}
public void AutoRun(){
iCar.run();
}
public void AutoStop(){
iCar.stop();
}
}


/**
* 奇瑞汽车
* Created by lirui on 2018/12/6.
*/
public class QQ implements ICar{
public  void run(){
System.out.println("奇瑞汽车启动");
}
public void stop(){
System.out.println("奇瑞汽车停止");
}
}


/**
* 江淮汽车
* Created by lirui on 2018/12/6.
*/
public class JAC implements ICar{
public void run(){
System.out.println("江淮汽车启动");
}
public void stop(){
System.out.println("江淮汽车停止");
}
}


©️2019 CSDN 皮肤主题: 创作都市 设计师: CSDN官方博客