当前主流的编程范式有三种:
1.结构化编程(structured programming)
2.面向对象编程(object-oriented programming)
3.函数式编程(functional programming)
这几种编程范式之间的关系如下:
1.起初是非结构化编程,指令(goto指令)可以随便跳转,数据可以随便引用。后来有了结构化编程,人们把 goto 语句去掉了,约束了指令的方向性,过程之间是单向的,但数据却是可以全局访问的;
2.后来面向对象编程的时候,人们干脆将数据与其紧密耦合的方法放在一个逻辑边界内,约束了数据的作用域,靠关系来查找;
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 )
电子商务web应用程序; 移动App; | ||
基于IPC的应用程序; | ||
进程内多线程调度; | ||
网络传输中的代理软件; | ||
多媒体协议; | ||
注册中心; | ||
GUI 应用程序; | ||
车辆识别及追踪; | ||
用于描述通信协议的语言 |
设计模式按照目的来分类有:创建、结构、行为三种,按照作用范围来分类有:类模式和对象模式两种。
1.创建型模式:用于创建对象,就是将对象的创建与使用分离。从而降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。
2.结构型模式:描述如何将类,对象,接口之间按某种布局组成更大的结构。
3.行为型模式:用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
23种设计模式如下:
• 用工厂模式隔离业务实现;
• 用策略模式消解业务流程分支;
• 用模板方法模式提取业务分支公共流程;
• 用建造者模式简化入参对象的构建难度;
• 用代理模式横向扩展通用能力(日志,异常处理);
• 用职责链模式对请求进行敏感词,防刷校验;
• 用命令模式让指令拥有了记忆;
// 贫困潦倒产生的和尚过程: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.输入参数1:挑水模式的实现(对应Tiaoshui实现类);
2.输入参数2:抬水模式的实现(对应Taishui实现类);
3.输入参数3:等不到水模式的实现(对应Dengshui实现类);
通过和尚人数,就可以动态获得对应的取水实现,即所谓的通过策略实现业务,对于使用方来说(主流程),无需关注取水的具体实现(解耦:业务流程稳定性的设计体现),新增取水方式时,只需要新增一个类实现就可以了,存量的实现和主流程都不会受到影响。
我们细化取水过程,取水过程一般需要三步:
1.拿起工具(扁担或者木棍);
2.到寺庙南面的小河边(步行);
3.装满水带回寺庙(挑水,抬水,等水);
我们可以将取水流程步骤进行模板化。
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("佛祖保佑,安检通过!");
}
}
寺庙里的和尚除了打水工作之外,还有很多工作要做,所有的工作安排都是按照主持的指令来执行的,比如某日清晨的工作安排如下:
1.一号和尚做早餐;
2.二号和尚扫庭院;
3.三号和尚敲古钟;
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();
}
}
模式与原则
1.设计原则是指导思想,设计模式是实现手段之一;
2.设计原则在实际开发中并不能做到完全遵守,往往是打破一些原则,遵守一些原则,来实现设计的合理性;(成本,性能)
3.设计模式往往是问题解决方案的骨架,有时候可以当做开发规范和任务拆分执行落地的技术手段;
4.一个设计模式,往往不仅仅采用一种设计原则,而是一些设计原则的整合;
5.设计模式不是一成不变的,可以根据问题场景,输出新的模式;
6.一个复杂场景问题,有时候需要多种设计模式的组合;
7.学设计模式,死记硬背是没用的,要从实践中习得;
8.避免设计过度,使简单的问题复杂化。一定要牢记简洁原则,设计模式是为了使设计简单,而不是更复杂;