1.2 什麼是編程範式
-
結構化編程(structured programming) -
面向對象編程(object-oriented programming) -
函數式編程(functional programming)
-
起初是非結構化編程,指令(goto指令)可以隨便跳轉,數據可以隨便引用。後來有了結構化編程,人們把 goto 語句去掉了,約束了指令的方向性,過程之間是單向的,但數據卻是可以全局訪問的; -
後來面向對象編程的時候,人們乾脆將數據與其緊密耦合的方法放在一個邏輯邊界內,約束了數據的作用域,靠關係來查找; -
到函數式編程的時候,人們約束了數據的可變性,通過一系列函數的組合來描述數據,從源到目標映射規則的編排,中間它是無狀態的;
1.3 什麼是多態特性
-
封裝即信息隱藏或數據保護,“數據結構"通過暴露有限的訪問接口,授權外部僅能通過"數據結構"提供的方法(函數)來訪問其內部的數據; -
繼承的好處是可以實現代碼複用,但不應過度使用,如果繼承的層次過深就會導致代碼可讀性和可維護性變差。因此建議少用繼承而多用組合模式; -
多態可以分爲變量的多態,方法的多態,類的多態。通常強調的是類的多態,多態的實現是指子類可以替換父類,在實際代碼運行過程中調用子類的方法實現;
class MyFile:
def write(self):
print('I write a message into file.')
class MyDB:
def write(self):
print('I write data into db. ')
def doIt(writer):
writer.write()
def demo():
myFile= MyFile()
myDB = MyDB()
doIt(myFile)
doIt(myDB )
2.1 瞭解架構模式
2.2 瞭解設計模式
-
創建型模式:用於創建對象,就是將對象的創建與使用分離。從而降低系統的耦合度,使用者不需要關注對象的創建細節,對象的創建由相關的工廠來完成。 -
結構型模式 :描述如何將類,對象,接口之間按某種佈局組成更大的結構。 -
行爲型模式 :用於描述程序在運行時複雜的流程控制,即描述多個類或對象之間怎樣相互協作共同完成單個對象都無法單獨完成的任務,它涉及算法與對象間職責的分配。
-
架構模式更像是宏觀戰略層面的設計,設計模式則更像是戰略目標拆解出來的具體任務的實現方案; -
軟件架構是軟件的一種搭建形式,往往規定了軟件的模塊組成,通信接口(含通信數據結構),組件模型,集成框架等,往往規定了具體的細節; -
設計模式是一種軟件的實現方法,是一種抽象的方法論,是爲了更好地實現軟件而歸納出來的有效方法; -
實現一種軟件架構,不同組成部分可能用到不同的設計模式,某個部分也可能可以採用不同的設計模式來實現;
3.1 適用場景
3.2 場景案例
-
用工廠模式隔離業務實現; -
用策略模式消解業務流程分支; -
用模板方法模式提取業務分支公共流程; -
用建造者模式簡化入參對象的構建難度; -
用代理模式橫向擴展通用能力(日誌,異常處理); -
用職責鏈模式對請求進行敏感詞,防刷校驗; -
用命令模式讓指令擁有了記憶;
工廠模式
// 貧困潦倒產生的和尚過程:1.大山裏;2.鬧饑荒;3.要喫飯;
一號和尚 = HeShangFactoty.getOneHeshang("貧困潦倒型");
// 走投無路產生的和尚過程:1.生性耿直;2.打死惡霸;3.要贖罪;
二號和尚 = HeShangFactoty.getOneHeshang("走投無路型");
// 天選之子產生的和尚過程:1.敏而好學;2.佛學感興趣;3.要廣大佛法;
三號和尚 = HeShangFactoty.getOneHeshang("天選之子型");
public interface Waterable {
Water getWater();
}
public class TiaoShui implements Waterable{
public Water getWater(){
System.out.println("先到山下去!");
return "水是挑上來的!";
}
}
public class TaiShui implements Waterable{
public Water getWater(){
System.out.println("先到山下去!");
return "水是擡上來的!";
}
}
public class DengShui implements Waterable{
public Water getWater(){
System.out.println("就坐在原地!");
return "水是等不來的!";
}
}
public class Factory {
/**
* 按照和尚數量生成取水對象
*
* @param heShangNum 和尚數量
* @return
*/
public static Waterable getWaterable(Integer heShangNum) {
switch (heShangNum) {
case 1:
return new TiaoShui();
case 2:
return new TaiShui();
case 3:
return new DengShui();
default:
throw new RuntimeException("廟小,裝不下那麼多和尚!");
}
}
}
策略模式
/**
* 通過入參和尚人數,就可以動態改變Waterable.getWater()的取水模式
* @param heShangNum
* @return
*/
public void getWater(Integer heShangNum) {
Waterable waterable = Factory.getWaterable(heShangNum);
Water water = waterable.getWater();// 取水
}
-
輸入參數1:挑水模式的實現(對應Tiaoshui實現類); -
輸入參數2:擡水模式的實現(對應Taishui實現類); -
輸入參數3:等不到水模式的實現(對應Dengshui實現類);
模板方法
-
拿起工具(扁擔或者木棍); -
到寺廟南面的小河邊(步行); -
裝滿水帶回寺廟(挑水,擡水,等水) ;
public interface Waterable {
Water getWater();
}
public abstract class AbstractWaterable implements Waterable {
@Override
public Water getWater() {
takeTool();
toRiver();
return moveWater();
}
/**
* 拿起工具
*/
protected abstract String takeTool();
/**
* 到河邊去
*/
protected String toRiver() {
System.out.println("走過去!");
return "步行";
}
/**
* 將水帶回來
*
* @return
*/
protected abstract Water moveWater();
}
public class TiaoShui extends AbstractWaterable {
protected String takeTool() {
return "扁擔";
}
protected Water moveWater() {
return "挑水";
}
}
public class Taishui extends AbstractWaterable{
protected String takeTool() {
return "木棍";
}
protected Water moveWater() {
return "擡水";
}
}
public class DengShui extends AbstractWaterable{
protected String takeTool() {
return "意念";
}
protected String toRiver() {
return "一動不動";
}
protected Water moveWater() {
return "無水";
}
}
/**
* 和尚取水:實現一個和尚挑水喝,兩個和尚擡水喝,三個和尚等水喝
*/
public void fetchWater(){
//
for (int heShangNum = 1; heShangNum < 4; heShangNum++) {
Waterable waterable = Factory.getWaterable(heShangNum);
Water water = waterable.getWater();
}
}
建造者模式
public class ToolBox {
private final String bianDan;
private final String muTong;
private final String muGun;
private ToolBox(TiaoBuilder builder){
this.bianDan=builder.bianDan;
this.muTong=builder.muTong;
this.muGun = null;
}
private ToolBox(TaiBuilder builder){
this.bianDan = null;
this.muTong = null;
this.muGun=builder.muGun;
}
private ToolBox(DengBuilder builder){
this.bianDan = null;
this.muTong = null;
this.muGun=null;
}
public static class TiaoBuilder{
private String bianDan;
private String muTong;
public TiaoBuilder setBianDan(String bianDan) {
this.bianDan = bianDan;
return this;
}
public TiaoBuilder setMuTong(String muTong) {
this.muTong = muTong;
return this;
}
public ToolBox build(){
return new ToolBox(this);
}
}
public static class TaiBuilder{
private String muGun;
private String muTong;
public TaiBuilder setMuGun(String muGun) {
this.muGun = muGun;
return this;
}
public TaiBuilder setMuTong(String muTong) {
this.muTong = muTong;
return this;
}
public ToolBox build(){
return new ToolBox(this);
}
}
public static class DengBuilder{
public ToolBox build(){
return new ToolBox(this);
}
}
//省略getter方法
}
ToolBox oneHeShangToolBox = new ToolBox.TiaoBuilder().setMuTong("小號木桶").setBianDan("小號扁擔").build();
ToolBox twoHeShangToolBox = new ToolBox.TaiBuilder().setMuTong("大號木桶").setMuGun("長號木棍").build();
ToolBox threeHeShangToolBox = new ToolBox.DengBuilder().build();
代理模式
public class WaterableProxy implements Waterable{
/**
* 被代理的原始對象
*/
private Waterable waterable;
public WaterableProxy(Waterable waterable) {
this.waterable = waterable;
}
public Water getWater() {
Water water = waterable.getWater();
// 增強的新功能,不管是挑水,擡水,等水,只有帶回來水,就可以
if(water != "無水"){
System.out.println("我敲一下木魚,打一次卡!");
}
return water;
}
}
public void doProxy(){
Waterable waterable = new Taishui();
WaterableProxy proxyWaterable = new WaterableProxy(waterable);
proxyWaterable.getWater();
}
責任鏈模式
-
禁止攜帶寵物; -
衣着穿戴整齊; -
其它業障,最終解釋權歸寺廟;
public interface SecureFilter {
void filter(Map context);
}
public class PetSecure implements SecureFilter{
public void filter(Map context) {
if(context.containsKey("寵物")){
throw new RuntimeException("請出去:禁止攜帶寵物進入!");
}
}
}
public class WearSecure implements SecureFilter{
public void filter(Map context) {
if(context.containsKey("光膀子")){
throw new RuntimeException("請出去:有傷風化者!");
}
}
}
public class OtherSecure implements SecureFilter{
public void filter(Map context) {
if(context.containsKey("大聲喧譁")){
throw new RuntimeException("請出去:佛門乃清淨之地!");
}
}
}
/**
* 安檢責任鏈實現
*/
class SecureChain implements SecureFilter{
// 注入PetSecure,WearSecure,OtherSecure等過濾器
private List<SecureFilter> secureFilterList;
/**
* 進入寺廟,進行安檢邏輯
* @param context
*/
public void filter(Map context) {
// 進行安檢流程
for (SecureFilter secureFilter : secureFilterList) {
secureFilter.filter(context);
}
System.out.println("佛祖保佑,安檢通過!");
}
}
命令模式
-
一號和尚做早餐; -
二號和尚掃庭院; -
三號和尚敲古鐘;
public class Command implements Serializable {
// 做早餐,打掃,敲鐘等指令標識
private OrderTypeEnum order;
// 正向執行OR逆向回滾
private Integer direction;
// 省略get和set方法
}
// 指令動作執行器,每種指令對應一個實現
public interface OrderHandler {
/**
* 執行邏輯
*
* @param callContext
* @return
*/
PipeResult execute(CallContext callContext);
/**
* 支持的命令類型:做早餐,打掃,敲鐘等命令標識
*
* @return
*/
OrderTypeEnum getOrderType();
}
// 指令類型管理器
public interface PipelineCmd {
/**
* 指令行定義
*
* @return
*/
Command getCommand();
/**
* 執行邏輯
*
* @param pipeContext
* @return
*/
PipeResult execute(PipeContext pipeContext);
/**
* 如果可以撤消指令,則此方法應返回true ,否則返回false
*
* @return
*/
default boolean isReversible() {
return true;
}
}
// 指令執行器管理器
public interface CmdHandler {
/**
* 業務執行
*
* @param callContext
* @return
*/
PipeResult execute(CallContext callContext);
/**
* 業務回滾(只回滾當前指令)
*
* @param callContext
* @return
*/
PipeResult rollback(CallContext callContext);
/**
* 全部回滾
*
* @param pipeContext
* @return
*/
PipeResult rollbackAll(PipeContext pipeContext);
}
public class ZhuChiCmd implements PipelineCmd {
private Command command;
private transient OrderHandler orderHandler;
public StepCmd(Command command, OrderHandler orderHandler) {
this.command = command;
this.orderHandler= orderHandler;
}
public PipeResult execute(PipeContext pipeContext) {
return orderHandler.execute(new CallContext(command, pipeContext));
}
// 省略get和set方法
}
public class Breakfast implements OrderHandler {
/**
* 執行邏輯
*
* @param callContext
* @return
*/
PipeResult execute(CallContext callContext){
System.out.println("做早餐啦!");
}
/**
* 支持的指令類型:做早餐,打掃,敲鐘等指令標識
*
* @return
*/
OrderTypeEnum getOrderType(){
return OrderTypeEnum.BREAKFAST;
}
}
public class Clean implements OrderHandler {
/**
* 執行邏輯
*
* @param callContext
* @return
*/
PipeResult execute(CallContext callContext){
System.out.println("打掃庭院啦!");
}
/**
* 支持的指令類型:做早餐,打掃,敲鐘等命令標識
*
* @return
*/
OrderTypeEnum getOrderType(){
return OrderTypeEnum.CLEAN;
}
}
public class Ring implements OrderHandler {
/**
* 執行邏輯
*
* @param callContext
* @return
*/
PipeResult execute(CallContext callContext){
System.out.println("敲鐘啦!");
}
/**
* 支持的命令類型:做早餐,打掃,敲鐘等指令標識
*
* @return
*/
OrderTypeEnum getOrderType(){
return OrderTypeEnum.Ring;
}
}
public class CmdFactory {
private List<OrderHandler> orderHandlerList;
/**
* 獲取指定指令條件的指令對象
*
* @param command
* @return
*/
public PipelineCmd getPipelineCmd(Command command) {
for (OrderHandler orderHandler : orderHandlerList) {
OrderTypeEnum orderTypeEnum = orderHandler.getOrderType();
if (orderTypeEnum.equals(command.getOrder())) {
return new ZhuChiCmd(command, orderHandler);
}
}
throw new RuntimeException("對不起主持:沒有多餘的和尚來執行新命令了!");
}
/**
* 獲取給定指令的回滾操作指令對象
*
* @param command
* @return
*/
public PipelineCmd getRollbackPipelineCmd(Command command) {
Command rollbackCommand = getRollbackCommand(command);
return getPipelineCmd(rollbackCommand);
}
}
public class CmdHandlerImpl implements CmdHandler {
private CmdFactory cmdFactory;
public PipeResult execute(CallContext callContext) {
PipelineCmd pipelineCmd = cmdFactory.getPipelineCmd(callContext.getCommand());
PipeResult pipeResult = pipelineCmd.execute(callContext.getPipeContext());
return pipeResult;
}
public PipeResult rollback(CallContext callContext) {
Command rollbackCommand = cmdFactory.getRollbackCommand(callContext.getCommand());
if (rollbackCommand == null) {
return new PipeResult("不需要回滾");
}
PipelineCmd pipelineCmd = cmdFactory.getPipelineCmd(rollbackCommand);
if (!pipelineCmd.isReversible()) {
return new PipeResult("不支持回滾");
}
PipeResult pipeResult = pipelineCmd.execute(callContext.getPipeContext());
return pipeResult;
}
public PipeResult rollbackAll(PipeContext pipeContext) {
// 命令執行備忘錄模式對象,這裏不再展開
Caretaker<Command> caretaker = pipeContext.getCaretaker();
// 拿到上一步執行命令,依次循環回滾
Command command = caretaker.pop();
while (command != null) {
PipelineCmd pipelineCmd = cmdFactory.getRollbackPipelineCmd(command);
if (pipelineCmd != null) {
pipelineCmd.execute(pipeContext);
}
command = caretaker.pop();
}
return new PipeResult();
}
}
3.3 實踐心得
設計原則
模式與原則
-
設計原則是指導思想,設計模式是實現手段之一; -
設計原則在實際開發中並不能做到完全遵守,往往是打破一些原則,遵守一些原則,來實現設計的合理性;(成本,性能) -
設計模式往往是問題解決方案的骨架,有時候可以當做開發規範和任務拆分執行落地的技術手段; -
個設計模式,往往不僅僅採用一種設計原則,而是一些設計原則的整合; -
設計模式不是一成不變的,可以根據問題場景,輸出新的模式; -
一個複雜場景問題,有時候需要多種設計模式的組合; -
學設計模式,死記硬背是沒用的,要從實踐中習得; -
避免設計過度,使簡單的問題複雜化。一定要牢記簡潔原則,設計模式是爲了使設計簡單,而不是更復雜;
-end-
本文分享自微信公衆號 - 京東雲開發者(JDT_Developers)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。