单一职责原则

不符合单一职责原则情况
package com.lvqiang.principle.singleResponsibilityPrinciple;

public class SingleResponsibilityPrinciple {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.run("汽车");
        vehicle.run("火车");
        vehicle.run("飞机");
    }
}
class Vehicle{
    public void run(String vehicle){
        System.out.println(vehicle + "在公路上行驶....");
    }
}
/*
* 从运行结果来看该种方式违背了单一职责原则,不同的交通工具共用一个方法,无法对某一交通工具进行单独特殊处理,
* 需要进行优化
* */
改进1
package com.lvqiang.principle.singleResponsibilityPrinciple;

public class SingleResponsibilityPrinciple2 {
    public static void main(String[] args) {
        RoadVehicle roadVehicle = new RoadVehicle();
        roadVehicle.run("汽车");
        WaterVehicle waterVehicle = new WaterVehicle();
        waterVehicle.run("轮船");
        RailwayVehicle railwayVehicle = new RailwayVehicle();
        railwayVehicle.run("高铁");
    }
}

class RoadVehicle{
    public void run(String vehicle){
        System.out.println(vehicle + "在公路上行驶....");
    }
}

class WaterVehicle{
    public void run(String vehicle){
        System.out.println(vehicle + "在水面行驶....");
    }
}
class RailwayVehicle{
    public void run(String vehicle){
        System.out.println(vehicle + "在铁路上行驶....");
    }
}
/**
 * 此种方式遵从了在方法上和类上职责单一原则,属于高度的单一,但是此种方式成本较高,有时会有些
 *
 */


改进二
package com.lvqiang.principle.singleResponsibilityPrinciple;

public class SingleResponsibilityPrinciple3 {
    public static void main(String[] args) {
        Vehicles vehicles = new Vehicles();
        vehicles.roadRun("汽车");
        vehicles.waterRun("轮船");
        vehicles.railwayRun("高铁");
    }
}
class Vehicles{
    public void roadRun(String vehicle){
        System.out.println(vehicle + "在公路上行驶....");
    }
    public void waterRun(String vehicle){
        System.out.println(vehicle + "在水面行驶....");
    }
    public void railwayRun(String vehicle){
        System.out.println(vehicle + "在铁路上行驶....");
    }
}
/**
 * 该方式实现了方法上的单一职责原则, 当有新的运行方式时直接在类上新增相应方法即可。
 *
 * 但是该类违反了类级别的单一原则,这是因为如果将每个交通方式都抽取出一个类,类中只有一个方法,像这种
 * 类中方法足够简单即可在一定程度上违背单一职责原则。
 */

接口隔离原则

如图:此时如果所有功能都集中在一个接口中,如果此时某个类只需用到其中某几个方法,而此时还是不得不实现该接口并实现接口中所有的方法。这样造成了代码将耦合性较高,不得不实现一些没必要的方法。不符合接口隔离原则。 需要进行细分,拆分成多个接口。

将之前那个大的接口拆分成几个独立的接口,实现了接口隔离,降低了耦合性。

  • 那么为什么不直接将所有接口都拆分成一个个独立的呢?

    如果是这样拆分,虽然确实实现了接口隔离原则 ,但是拆分粒度不免会有些过于细,在实现接口时不免有些过于累赘,大部分情况下都无需拆分过于精细。

依赖倒置原则

未遵守依赖倒置原则出现问题
package com.lvqiang.principle.singleResponsibilityPrinciple.dependencyInversionPrinciple;

public class DependencyInversionPrinciple1 {
    public static void main(String[] args) {
        Person person = new Person();
        Email email = new Email();
        person.receive(email);
        WeiXin weiXin = new WeiXin();
        person.receive(weiXin);
    }
}
class Person{
    public void receive(Email email){
        email.getMsg();
    }
    public void receive(WeiXin weiXin){
        weiXin.getMsg();
    }
}
class Email{
    public void getMsg(){
        System.out.println("Email info....");
    }
}
class WeiXin{
    public void getMsg(){
        System.out.println("WeiXin info....");
    }
}

/**
 * 如果是使用此方法实现,功能确实能实现,可当我们后续需要再新增其他通讯方式如QQ 等既需要新增QQ类, 还需要在Person中昨天qq相对应的获取信息的方式
 * 代码改动较大,针对这种情况便可使用控制反转,抽取出一个通用的功能接口,通过接口传递来实现。
 *
 */
使用依赖倒置带来的好处
package com.lvqiang.principle.singleResponsibilityPrinciple.dependencyInversionPrinciple;

public class DependencyInversionPrinciple2 {
    public static void main(String[] args) {
        Person2 person = new Person2();
        Receive receive= new Email2();
        person.receive(receive);
        receive = new WeiXin2();
        person.receive(receive);
    }
}

class Person2{
    public void receive(Receive receive){
        receive.getMsg();
    }
}

interface Receive{
    public void getMsg();
}

class Email2 implements Receive{
    public void getMsg(){
        System.out.println("Email info....");
    }
}

class WeiXin2 implements Receive{
    public void getMsg(){
        System.out.println("WeiXin info....");
    }
}

/**
 * 通过使用依赖倒置,使使用的类都依赖于公共的接口,极大的方便了程序的扩展,用法也更加灵活多变。
 *
 * 实现方式可以有三种:
 *  1.接口传递
 *  2.构造方法传递
 *  3.setter方法传递
 *
 */
//2.构造方法传递
//class Person2{
//    Receive receive;
//    public Person2(Receive receive){
//        this.receive = receive;
//    }
//    public void receive(){
//        receive.getMsg();
//    }
//}

//3.setter方法传递
//class Person2{
//    Receive receive;
//
//    public void setReceive(Receive receive){
//        this.receive = receive;
//    }
//    public void receive(){
//        receive.getMsg();
//    }
//}

里氏替换原则

子类可以替换父类出现在父类能够出现的任何地方(即尽量不要重写父类中的方法),其实使用继承会使得使这两个类耦合性增加了,给程序带来了侵入性,可以通过使用组合、聚合和依赖来实现。

开闭原则

方式一:

package com.lvqiang.principle.singleResponsibilityPrinciple.openClosePrinciple;

/**
 * 需求:实现一个可以画任意图形功能
 *
 */
public class OpenClosePrinciple1 {
    public static void main(String[] args) {
        ShapEdite shapEdite = new ShapEdite();
        shapEdite.drawShap(new Circular());
    }
}
class ShapEdite{
    public void drawShap(Shap s){
        if(s.s_type == 0){
            System.out.println("无图形");
        }else if (s.s_type == 1){
            drawCircular();
        }else if(s.s_type == 2){
            drawRectangle();
        }else{
            drawTriangle();
        }
    }
    public void drawCircular(){
        System.out.println("画圆形");
    }

    public void drawRectangle(){
        System.out.println("画矩形");
    }
    public void drawTriangle(){
        System.out.println("画三角形");
    }
}
abstract class Shap{
    int s_type;

}

class Circular extends Shap{

    public Circular() {
        super.s_type = 1;
    }
}

class Rectangle extends Shap{

    public Rectangle() {
        super.s_type = 2;
    }

}
class Triangle extends Shap{

    public Triangle() {
        super.s_type = 3;
    }
}
/**
 * 此种实现方式存在的弊端:当每新增一个新的图形时,不但需要编写新的图形类,还需要再ShapEdite类中增加新的类型判断,不符合开闭原则的设计
 * 同时也违背了中少用if-else 判断。
 * 改进:使用策略模式代替if-else ,  将通用的画图方法抽取到出来  放在抽象类中。
 */

方式二

package com.lvqiang.principle.singleResponsibilityPrinciple.openClosePrinciple;

/**
 * 需求:实现一个可以画任意图形功能
 */
public class OpenClosePrinciple2 {
    public static void main(String[] args) {

        ShapEdite2 shapEdite2 = new ShapEdite2();
        shapEdite2.drawShap(new Rectangle2());
    }
}

class ShapEdite2 {
    public void drawShap(Shap2 s) {
        s.draw();
    }
}

abstract class Shap2 {
    int s_type;

    public abstract void draw();
}

class Circular2 extends Shap2 {
    @Override
    public void draw() {
        System.out.println("画圆形");
    }
}

class Rectangle2 extends Shap2 {

    @Override
    public void draw() {
        System.out.println("画矩形");
    }
}

class Triangle2 extends Shap2 {
    @Override
    public void draw() {
        System.out.println("画三角形");
    }
}
/**
 * 当还需要再增加需求时,直接通过新增实体类即可达到应对 变化的需求,而无需修改已有的代码。
 * 只是对模块的扩张方面开放(新实体类的增加), 而对代码的就该关闭(修改EditeShap类)。遵从了开闭的原则
 * 同时使用了策略模式避免出现了大量的if-else的判断
 */