一、面向对象通用基本原则:抽象、继承、多态
简单的讲,所谓设计模式就是用更专业和细致的的语言描述抽象、继承和多态。在实际开发中,如果一时想不到要用哪种设计模式来优化自己的代码,就使用最基本的抽象、继承、多态来抽取公共接口,将动态的代码用接口+参数实现的方式进行。
但是,该模式要注意,继承是有原罪的:
对类的局部改动,尤其超类的局部改动,会影响其他部分。影响会有溢出效应。
例如:
public abstract class Duck {
...;
public void Fly() {
System.out.println("~~im fly~~");
}
};
这样的一个超类,就规定了,所有的鸭子都是可以飞的。
但是,如果是一只唐老鸭呢?
public class TangDuck extends Duck {
...;
@Override
public void Fly() {
System.out.println("~~no fly~~");
}
}
如果是北京烤鸭呢?
public class PeckingRoastDuck extends Duck {
...;
@Override
public void Fly() {
System.out.println("~~no fly~~");
}
}
所以,可以看到,传统OO模型中的继承,超类设计不合理,会对子类产生影响,增加子类的开发量。
那么,如何破局呢?
需要新的设计方式,应对项目的扩展性,降低复杂度:
1)分析项目变化与不变部分,提取变化部分,抽象成接口+实现;
2)鸭子哪些功能是会根据新需求变化的?叫声、飞行…
首先,将可变动的接口抽离出来,做成接口。
接口:
1)public interface FlyBehavior
{
void fly();}
2)public interface QuackBehavior
{
void quack();};
public abstract class Duck {
FlyBehavior mFlyBehavior;
QuackBehavior mQuackBehavior;
public Duck() { }
public void Fly() {
mFlyBehavior.fly();
}
public void Quack() {
mQuackBehavior.quack();
}
public abstract void display();
}
public class GreenHeadDuck extends Duck {
public GreenHeadDuck() {
mFlyBehavior = new GoodFlyBehavior();
mQuackBehavior = new GaGaQuackBehavior();
}
@Override
public void display() {...}
}
此处,贴出一段具体业务的代码,场景为在使用Mq的过程中,由于需要根据不同业务类型调用不同的接口,所以设计了一个策略模式的接口调用类。
@Component
public class DeclServiceFactory {
@Autowired
private ReDeclArrivalService reDeclArrivalService;
@Autowired
private ReDeclDepartureService reDeclDepartureService;
@Autowired
private ReDeclInventoryService reDeclInventoryService;
@Autowired
private ReDeclLogisticsService reDeclLogisticsService;
@Autowired
private ReDeclOrderService reDeclOrderService;
@Autowired
private ReDeclReceiptsService reDeclReceiptsService;
@Autowired
private ReDeclSummaryApplyService reDeclSummaryApplyService;
@Autowired
private ReDeclWayBillService reDeclWayBillService;
@Autowired
private ReDeclInvtCancelService reDeclInvtCancelService;
public DeclService get(String msgType) {
DeclService service = null;
MsgTypeEnum typeEnum = this.getEnum(msgType);
if(typeEnum == null) { return null;}
switch (typeEnum) {
case ORDER: //订单
service = reDeclOrderService;
break;
case RECEIPTS: //收款单
service = reDeclReceiptsService;
break;
case LOGISTICS: //物流运单
service = reDeclLogisticsService;
break;
case ARRIVAL: //物流运抵单
service = reDeclArrivalService;
break;
case DEPARTURE: //物流离境单
service = reDeclDepartureService;
break;
case INVENTORY: //申报清单
service = reDeclInventoryService;
break;
case INVT_CANCEL: //撤销清单申请
service = reDeclInvtCancelService;
break;
case WAY_BILL: //清单总分单
service = reDeclWayBillService;
break;
case SUMMARY_APPLY: //汇总申请单
service = reDeclSummaryApplyService;
break;
default:
break;
}
return service;
}
private MsgTypeEnum getEnum(String msgType) {
return MsgTypeEnum.getEnumByMsgType(msgType);
}
}
好处:将行为方法抽离了出来,子类新增行为比较简单,行为类可以被更好的复用,组合更方便。具备继承带来的复用好处,又不会像传统的OO超类设计导致的子类复用中产生溢出效应,减少麻烦。
小结:
策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者。
直白一点就是:尽可能将行为方法设计为行为接口,例如:fly功能接口,不同的飞行方式去继承该接口,在类调用fly接口的时候,使用构造函数初始化自己需要的fly接口实现类方法即可。