携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
简介
开闭原则,即软件设计中的对象,如模块、类、方法都应该满足对修改关闭,对拓展开放。故我们在新增功能的时候不应该是去修改之前已实现的功能,而是应该新增模块、类或者方法,这样才能保证不影响之前稳定的代码功能。
应用
public class Shopping {
public static void main(String[] args) {
Shopping shopping = new Shopping();
shopping.pay("wx");
}
public void pay(String type) {
if (Objects.equals("zfb", type)) {
payWithZfb();
}else if(Objects.equals("wx", type)) {
payWithWx();
}
}
public void payWithZfb(){
System.out.println("zfb pay...");
}
public void payWithWx(){
System.out.println("wx pay...");
}
}
如上述代码所示,此处有一个购买东西支付的场景,支付方式目前有微信和支付宝支付。一个不满足开闭原则的实现方式就是,通过if/else来判断用户选择的支付方式来调用对应的支付方法,这样如果后续需要增加财富通等支付方式就要在此处修改代码,而修改代码则会造成可能的缺陷和问题,此方法不满足开闭原则。
那我们该如何改造呢?
首先定义一个支付方式的接口
public interface BasePay {
void pay();
}
定义各种支付的实现类
public class WxPay implements BasePay {
@Override
public void pay() {
System.out.println("wx pay...");
}
}
public class ZfbPay implements BasePay {
@Override
public void pay() {
System.out.println("zfb pay...");
}
}
调用
public class Shopping {
public static HashMap payRoutes = new HashMap();
static {
payRoutes.put("Wx", new WxPay());
payRoutes.put("Zfb", new ZfbPay());
}
public static void main(String[] args) {
Shopping shopping = new Shopping();
BasePay wx = (BasePay)payRoutes.get("Wx");
wx.pay();
}
public void pay(BasePay basePay) {
basePay.pay();
}
}
这样同样能实现通过不同场景下传入payRoutes中的key值即可获取到对应的支付方式的调用方法。而且这种情况后续如果增加财富通支付方式,那同样可以通过实现BasePay接口来实现,而不会影响此处使用微信支付的调用,做到了对修改关闭,对拓展开放。
了解过设计模式的同学在这里就发现这里实际上就是使用了策略模式来实现的。当然这里如果引入了Spring框架,就可以直接通过查找所有实现了BasePay的bean即可。
总结
一般情况下,在一个类或者方法中通过条件等硬编码实现各种条件分支的均可以抽离出来,通过继承抽象类或者实现接口的形式来实现开闭原则。但是也要具体情况具体分析,有些肯定固定场景和固定业务就没必要考虑拓展。