Java 设计模式6大原则之

Java 设计模式6大原则之,第1张

对于设计模式的原则,不同的书说法不一样,有的6个有的7个,单一职责原则和接口隔离原则多数只提了一个。

开闭原则为最重要的面向对象设计原则,它是面向对象的可复用设计的第一块基石。其他几条,则可以看作是开闭原则的实现方法。设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。

单一职责原则

类职责要单一,一个类应该只做一件事情。

开闭原则(OCP)
  • 概念

一个软件实体(类、模块和方法)应该对扩展开放,对修改关闭。当功能需要变化的时候,我们应该是通过扩展的方式实现,而不是通过修改已有的代码来实现。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,设计满足开闭原则的软件系统也变得越来越重要。

  • 场景分析

一个软件随着时间的推移会不断更新升级,那么在程序进行更新、升级的过程中,我们应该尽量避免在原来代码上进行修改,因为这样会使得原来的程序出现异常或变得不够稳定,并且更改后我们需要对原有的功能进行反复的测试,这样的做法是不提倡的。

  • 解决方案

当程序功能需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。

  • 程序设计        

        ○ 现有如下程序

        目前程序支持两种银行的转账,两种银行的转账手续费各不一样,1年开发小白写的代码如下:

public class Test {

    public static void main(String[] args) {
        TransferAccount transferAccount = new TransferAccount();
        transferAccount.transfer("icbc");
    }

}

//交通银行
class CBCBank {
    //转账100,扣除手续费1块钱
    int transferMoney() {
        return 100 - 1;
    }
}

//工商银行
class ICBCBank {
    //转账100,扣除手续费2块钱
    int transferMoney() {
        return 100 - 2;
    }
}

//转账
class TransferAccount {
    //转账方法
    public void transfer(String type) {
        if ("icbc".equals(type)) {
            ICBCBank bank = new ICBCBank();
            int i = bank.transferMoney();
            System.out.println("icbc银行转账了:" + i + "块钱");
        } else if ("cbc".equals(type)) {
            CBCBank bank = new CBCBank();
            int i = bank.transferMoney();
            System.out.println("cbc银行转账了:" + i + "块钱");
        }
    }
}

上述代码在线上运行的非常不错,但随着业务的扩大,需要加入新的银行转账功能,此时开发小白说没有问题,三下五除二,加了一个银行,并且更改了TransferAccount的方法,如下:

public class Test {

    public static void main(String[] args) {
        TransferAccount transferAccount = new TransferAccount();
        transferAccount.transfer("icbc");
    }
}

//交通银行
class CBCBank {
    //转账100,扣除手续费1块钱
    int transferMoney() {
        return 100 - 1;
    }
}

//工商银行
class ICBCBank {
    //转账100,扣除手续费2块钱
    int transferMoney() {
        return 100 - 2;
    }
}

//农业银行
class ABCBank {
    //转账100,扣除手续费3块钱
    int transferMoney() {
        return 100 - 3;
    }
}

//转账
class TransferAccount {
    //转账方法
    public void transfer(String type) {
        if ("icbc".equals(type)) {
            ICBCBank bank = new ICBCBank();
            int i = bank.transferMoney();
            System.out.println("icbc银行转账了:" + i + "块钱");
        } else if ("cbc".equals(type)) {
            CBCBank bank = new CBCBank();
            int i = bank.transferMoney();
            System.out.println("cbc银行转账了:" + i + "块钱");
        } else if ("abc".equals(type)) {
            //产品经理说,小白,今天功能要增加了,加了一个ABCBank转账
            ABCBank bank = new ABCBank();
            bank.transferMoney();
            //问题:每次新增功能都会修改TransferAccount中的转账逻辑,如果不小心把方法改坏了,里面之前支持的转账功能都不好使了,
            //本来只是想增加一个新的功能,结果影响到了老的功能,造成老的功能就要进行反复的测试。此时就违反了开闭原则,开闭原则是
            //扩展不是新增,尤其不可以修改现有的方法。
        }
    }
}

上述代码需要修改transfer已有功能的源码,增加新的逻辑判断,违反了开闭原则,现对该系统进行重构,使其符合开闭原则。

        ○ 使用开闭原则后的程序

           程序中transfer方法需要对每一种银行进行硬编程,业务发生变更该代码就要发生改变,故进行调整,使用抽象化的方法对系统进行重构,使得业务扩展时改代码不受影响,具体做法如下

           增加一个抽象银行类AbstractBank,将各种具体的银行类作为其子类;

public class Test {

    public static void main(String[] args) {
        TransferAccount transferAccount = new TransferAccount();
        transferAccount.transfer(new CBCBank());
    }

}

//交通银行
class CBCBank extends AbstractBank {
    //转账100,扣除手续费1块钱
    int transferMoney() {
        return 100 - 1;
    }
}

//工商银行
class ICBCBank extends AbstractBank {
    //转账100,扣除手续费2块钱
    int transferMoney() {
        return 100 - 2;
    }
}

//农业银行
class ABCBank extends AbstractBank {
    //转账100,扣除手续费3块钱
    int transferMoney() {
        return 100 - 3;
    }
}

//抽象类、接口都可以,反正需要做到足够抽象
abstract class AbstractBank {
    abstract int transferMoney();
}

//转账账户
class TransferAccount {
    //转账方法
    public void transfer(AbstractBank bank) {
        System.out.println("转账前的校验");
        int i = bank.transferMoney();
        System.out.println("转账了:" + i + "块钱");
        System.out.println("转账后的通知");
    }
}

总结:

将程序调整满足开闭原则后,后续代码更新,我们无需再修改TransferAccount转账方法,而只需要加入一个新的银行,将新的银行继承AbstractBank即可。

  • 开闭原则优点

        ○ 可复用性

        ○ 可维护性

  • 注意事项

        ○ 通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法

        ○ 参数类型、引用对象尽量使用接口或者抽象类,而不是具体的实现类

        ○ 抽象层尽量保持稳定,一旦确定即不允许修改,这对开发人员的经验有一定要求

资料来源:B站视频https://www.bilibili.com/video/BV17z4y117qn?spm_id_from=333.999.0.0

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/916296.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存