Java设计模式


目前字数: 5746,该文章会持续更新。预计目标完结文字大约为5-10万字。


1. Java设计模式

1.1 单一职责原则

1.1.1 基本介绍

对类来说,即一个类应该只负责一项职责。如果A类负责两个不同的职责,如:职责1,职责2。当职责1需求变更而需要更改A时,可能造成职责2执行错误,所以需要将A这个类的粒度分解为A1,A2。

1.1.2 代码小案例

首先写下以下一段Java代码,非常基础的内容。

package principle.singleresibility;

/**
 * 单一职责,小案例1
 * 交通小案例
 */
public class SingleResponsibility1 {

    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 + " 在公路上跑...");
    }
}

在运行后,我们会得到以下结果

摩托车 在公路上跑...
汽车 在公路上跑...
飞机 在公路上跑...

这时候我们就会发现有点不对,摩托和汽车在公路上跑就算了,为什么飞机也能在公路上跑。你管地上的也就算了,飞机你也要管。也就是说,在这里违反了单一职责原则。

那么我们就需要有一个解决方案,根据交通工具运行的方式不同,分解成不同的类即可。

package principle.singleresibility;

/**
 * 单一职责,小案例1
 * 交通小案例
 */
public class SingleResponsibility2 {

    public static void main(String[] args) {

        // 进行代码测试,通过接口来new对象,分别测试飞机,潜艇,小汽车
        VehicleRun car = new RoadVehicle();
        car.run("小汽车");

        VehicleRun aircraft = new AirVehicle();
        aircraft.run("飞机");

        VehicleRun submarine = new WaterVehicle();
        submarine.run("潜艇");

    }

}

/**
 * 交通工具接口,都可以run,
 * 这样做有效的实现了单一责任,但是他的花销非常大。需要很多个类。且改动很大。即将类分解,同时修改客户端。
 */
interface VehicleRun {
    void run(String vehicle);
}

/**
 * 路上跑的交通工具类
 */
class RoadVehicle implements VehicleRun {
    public void run(String vehicle) {
        System.out.println(vehicle + " 公路运行...");
    }
}

/**
 * 天空运行的交通工具类
 */
class AirVehicle implements VehicleRun {
    public void run(String vehicle) {
        System.out.println(vehicle + " 天空运行...");
    }
}

/**
 * 水里运行的交通工具类
 */
class WaterVehicle implements VehicleRun {
    public void run(String vehicle) {
        System.out.println(vehicle + " 水中运行...");
    }
}

但是,这样依然存在问题。这样做有效的实现了单一责任,但是他的花销非常大。需要很多个类。且改动很大。即将类分解,同时修改客户端。也就是说,上述代码依然是可以优化的,我们可以把他全部写在一个类中。

package principle.singleresibility;

public class SingleResponsibility3 {

    public static void main(String[] args) {

        Vehicle2 vehicle2 = new Vehicle2();

        vehicle2.run("汽车");

        vehicle2.runAir("飞机");

        vehicle2.runWater("轮船");

    }

}

/**
 * 方式三
 * 这种方式并没有对原来的类做大修改,只是增加了方法。
 * 他在一定程度上,并没有遵守单一原则,但是在方法拆封上,依然是遵守了单一原则。
 */
class Vehicle2 {
    public void run(String vehicle) {
        System.out.println(vehicle + " 在公路上运行...");
    }

    public void runAir(String vehicle) {
        System.out.println(vehicle + " 在天上运行...");
    }

    public void runWater(String vehicle) {
        System.out.println(vehicle + " 在水里运行...");
    }
}

1.1.3 小结

  1. 降低类的复杂度,一个类只负责一项职责
  2. 提高类的可读性,可维护性
  3. 降低变更引起的风险
  4. 通常情况下,我们应当遵守单一职责原则。只有逻辑足够简单,才可以在代码级别违反单一职责原则;只有类中的方法量足够少,我们才可以在方法级别保持单一职责原则。

1.2 接口隔离性原则

1.2.1 基本介绍

接口隔离性原则又称 Interface Segregation Principle,客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立于最小的接口上。

1.2.2 代码小案例

类A通过接口Interface1依赖(使用)类B,类c通过接口Interface1依赖(使用)类D,如果接口Interface1对于类A和类c来说不是最小接口那么类B和类D必须去实现他们不需要的方法。

按隔离原则应当这样处理:将接口Interface1拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则

请必要看清楚代码和代码内的注释内容。

package principle.segregation;

/**
 * 接口隔离性原则, 小案例
 */
public class Segregation1 {
}

/**
 * 接口的定义
 */
interface Interface1 {
    void operation1();
    void operation2();
    void operation3();
    void operation4();
    void operation5();
}

class B implements Interface1 {

    @Override
    public void operation1() {
        System.out.println("B 实现了 operation1");
    }

    @Override
    public void operation2() {
        System.out.println("B 实现了 operation2");
    }

    @Override
    public void operation3() {
        System.out.println("B 实现了 operation3");
    }

    @Override
    public void operation4() {
        System.out.println("B 实现了 operation4");
    }

    @Override
    public void operation5() {
        System.out.println("B 实现了 operation5");
    }
}

class D implements Interface1 {
    @Override
    public void operation1() {
        System.out.println("D 实现了 operation1");
    }

    @Override
    public void operation2() {
        System.out.println("D 实现了 operation2");
    }

    @Override
    public void operation3() {
        System.out.println("D 实现了 operation3");
    }

    @Override
    public void operation4() {
        System.out.println("D 实现了 operation4");
    }

    @Override
    public void operation5() {
        System.out.println("D 实现了 operation5");
    }
}

/**
 * A 依赖于B,且只使用接口的1,2,3个方法
 */
class A {
    public void operation1(Interface1 interface1) {
        interface1.operation1();
    }

    public void operation2(Interface1 interface2) {
        interface2.operation2();
    }

    public void operation3(Interface1 interface3) {
        interface3.operation3();
    }
}

/**
 * C 依赖于D,只用到1, 4, 5个方法
 */
class C {
    public void operation1(Interface1 interface1) {
        interface1.operation1();
    }

    public void operation4(Interface1 interface4) {
        interface4.operation4();
    }

    public void operation5(Interface1 interface5) {
        interface5.operation5();
    }
}

上述代码就会存在一个问题,B和D都实现了Interface1,也就是说五个方法都必须要重写,那么A依赖于B,C依赖于D,且A只需要使用1,2,3方法,C只需要使用1,4,5方法。也就是说,在B中,会有4,5方法用不到,D中会有2,3方法用不到。

解决方法,将接口Interface1拆分为几个独立的接口,类A和类C分别与他们需要的接口建立依赖关系,也就是采用接口隔离原则。接口Interface1中出现的情况,根据实际情况拆分为三个接口。

  1. Interface1 —> operation1
  2. Interface2 —> operation2, operation3
  3. Interface3 —> operation4, operation5

上述拆分也很好理解,一共有五个方法,分别是 1 2 3 4 5,A使用到了1 2 3, C使用到了 1 4 5,把公共的1单独拆出来一份,然后分别拆不同的内容,也就是拆出来一个2 3,在拆出来一个4 5

package principle.segregation.improve;

/**
 * 接口隔离性原则案例改进
 */
public class SegregationImprove {

    public static void main(String[] args) {

        A a = new A();
        a.operation1(new B());
        a.operation2(new B());
        a.operation3(new B());

        C c = new C();
        c.operation1(new D());
        c.operation4(new D());
        c.operation5(new D());
    }

}

interface Interface1 {
    void operation1();
}

interface Interface2 {
    void operation2();
    void operation3();
}

interface Interface3 {
    void operation4();
    void operation5();
}

class B implements Interface1, Interface2 {

    @Override
    public void operation1() {
        System.out.println("B 实现了 operation1");
    }

    @Override
    public void operation2() {
        System.out.println("B 实现了 operation2");
    }

    @Override
    public void operation3() {
        System.out.println("B 实现了 operation3");
    }
}

class D implements Interface1, Interface3 {
    @Override
    public void operation1() {
        System.out.println("D 实现了 operation1");
    }

    @Override
    public void operation4() {
        System.out.println("D 实现了 operation4");
    }

    @Override
    public void operation5() {
        System.out.println("D 实现了 operation5");
    }
}

/**
 * 创建A和C分别依赖于B和D实现各自对应的方法
 * A: 1, 2, 3
 * C: 1, 4, 5
 */
class A {
    public void operation1(Interface1 interface1) {
        interface1.operation1();
    }

    public void operation2(Interface2 interface2) {
        interface2.operation2();
    }

    public void operation3(Interface2 interface2) {
        interface2.operation3();
    }
}

class C {
    public void operation1(Interface1 interface1) {
        interface1.operation1();
    }

    public void operation4(Interface3 interface3) {
        interface3.operation4();
    }

    public void operation5(Interface3 interface3) {
        interface3.operation5();
    }
}

你可能感兴趣的:(Java,经验分享,java,设计模式,开发语言)