• 模板模式讲解二


    一、何为模板

    在阎宏博士的《JAVA与模式》一书中开头是这样描述模板方法(Template Method)模式的:

      模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。

    二、模式结构设计

      父类定义成一个抽象类,有一个具体实现方法,在这个具体实现方法会去调用此抽象类定义的抽象方法,这些抽象方法由子类继承实现,因为不同的业务逻辑是需要由不同的子类完成的。父类的具体实现方法,只是把这些子类的抽象方法执行的共同点抽取出来。有点不好理解,直接看图吧

     

    三、操作数据库的模板模式设计

      场景 : 大型的电商网站,如淘宝、京东、苏宁等。仔细分析下,领域模型大同小异。无非就是围绕商品、规格、订单等模型来展开。一个商品,它的模型是怎么样的呢?商品名字、价格等。但我们很难把商品的所有属性定义出来,并不是所有的商品属性都是一样的。所以,这时商品就有了另一个极其灵活的属性-->扩展属性。扩展属性,顾名思义,可扩展,视需求定义。比如,我们定义商品的购买限制规则,每个ID只能购买一件等等。商品的扩展属性很多,在保存商品属性信息,同时也需要保存扩展属性。保存扩展属性信息,操作可以细分为如下三种 : 

    ①、创建商品信息,插入扩展属性

    ②、更新商品信息,更新扩展属性(假设属性表,A商品有三条扩展属性信息,origin_id=[123,456,789] ,  现在需要更新扩展属性信息,new_id = [456,520] )

    a、插入新的扩展属性 : id = 520

    b、更新扩展属性 : id = 456

    c、删除不需要的扩展属性 : id = 123,789

    ③、删除商品信息,删除扩展属性

    我们的重点是讲第②点,update商品信息,其更新规则如下:

    a、属性表没有的,参数有的,则插入

    b、属性表有的,参数有的,则更新

    c、属性有的,参数没有的,则删除

    更新商品扩展属性伪代码如下:

     1     public Result<GoodsDTO> save(List<GoodsDTO> newInfo) {
     2         // 获取商品的老扩展属性信息
     3         List<GoodsDTO> oldInfo = getGoodsAttrByGoodsId(Long goodsId);
     4         
     5         for(GoodsDTO newGoods : newInfo) {
     6             boolean isNeedInsert = true;
     7             for(GoodsDTO oldGoods :oldInfo) {
     8                 if(newGoods.getId() = oldGoods.getId()) {// 属性表有的,参数有的,则为更新
     9                     isNeedInsert = false;
    10                     updateAttr(newGoods);
    11                     break;
    12                 }
    13             }
    14             if(isNeedInsert) {// 属性表没有的,参数有的,则为插入
    15                 insertAttr(newGoods);
    16             }
    17         }
    18         for(GoodsDTO oldGoods : newInfo) {
    19             boolean isNeedDelete = true;
    20             for(GoodsDTO newGoods :oldInfo) {
    21                 if(newGoods.getId() = oldGoods.getId()) {// 属性表有的,参数没有的,则为删除
    22                     isNeedDelete = false;
    23                     break;
    24                 }
    25             }
    26             if(isNeedDelete) {
    27                 deleteAttr(oldGoods);
    28             }
    29         }
    30     }

    代码逻辑不复杂,但这种逻辑写法,严格来说,是非业务性代码,浸入了我们的业务系统。我们再想想,同样,规格、订单等也有扩展属性。它们的操作规则大同小异。试想,让

    你每次更新扩展属性时,写这种恶心逻辑,你能坚持写下去么?如果,后续我们更新扩展属性的规则变了呢?比如,不再根据扩展属性的Id来判断是否add、update、delete?那这时问题来了,你是不是把所有有此逻辑的代码找出来,改改?显然,谁也不愿意这样干。这时,模板设计就派上场了。可以把改动点抽取粗来,集中在一个父类的具体实现方法。

    insert 、 update 、delete这些不同的DAO对应不同的表操作,由具体的子类去继承父类,并强迫子类去实现这些抽象方法。

    父类(模板)

     1 public abstract class DoTemp<T extends BaseDO> {
     2     
     3     public abstract void insert(T t);
     4     
     5     public abstract void update(T target, T orign);
     6 
     7     public abstract void delete(T t);
     8     
     9     protected void execute(List<T> target, List<T> orign) {
    10         if(target != null) {
    11             for(T t : target) {
    12                 boolean isNeedInsert = true;
    13                 for(T o : orign) {
    14                     if(t.getId() == o.getId()) {
    15                         this.update(t, o);
    16                         isNeedInsert = false;
    17                     }
    18                 }
    19                 if(isNeedInsert) {
    20                     this.insert(t);
    21                 }
    22             }
    23         }
    24         
    25         if(orign != null) {
    26             for(T o : orign) {
    27                 boolean isNeedDel = true;
    28                 for(T t : target) {
    29                     if(t.getId() == o.getId()) {
    30                         isNeedDel = false;
    31                     }
    32                 }
    33                 if(isNeedDel) {
    34                     this.delete(o);
    35                 }
    36             }
    37         }
    38     }
    39 }

     实体类:

     1 public class GoodsDO extends BaseDO {
     2 
     3     private int id;
     4     
     5     private String name;
     6 
     7     @Override
     8     public String toString() {
     9         return ToStringBuilder.reflectionToString(this);
    10     }
    11 
    12     public GoodsDO() {
    13 
    14     }
    15 
    16     public GoodsDO(int id, String name) {
    17         this.id = id;
    18         this.name = name;
    19         super.id = id;
    20     }
    21 
    22     public int getId() {
    23         return id;
    24     }
    25 
    26     public void setId(int id) {
    27         this.id = id;
    28     }
    29 
    30     public String getName() {
    31         return name;
    32     }
    33 
    34     public void setName(String name) {
    35         this.name = name;
    36     }
    37 }
    38 
    39 
    40 
    41 public class BaseDO {
    42     
    43     public int id;
    44 
    45     public int getId() {
    46         return -1;
    47     }
    48 
    49     public void setId(int id) {
    50         
    51     }
    52 }
    View Code

    子类:

    public class GoodsDoTempImpl extends DoTemp<GoodsDO> {
        
        @Override
        public void insert(GoodsDO t) {
            // TODO Auto-generated method stub
            System.out.println("-------- insert ---------" + JSON.toJSONString(t));
        }
    
        @Override
        public void update(GoodsDO target, GoodsDO orign) {
            // TODO Auto-generated method stub
            System.out.println("-------- update ---------" + JSON.toJSONString(target) + "---- 更新后值为 ----" + JSON.toJSONString( orign));
        }
    
        @Override
        public void delete(GoodsDO t) {
            // TODO Auto-generated method stub
            System.out.println("-------- delete ---------" + JSON.toJSONString(t));
        }
    }

    测试类 : 

     1 public class Client {
     2 
     3     public static void main(String[] args) {
     4         
     5         
     6         test_dotemp();
     7     }
     8     
     9     public static void test_dotemp() {
    10         
    11         List<GoodsDO> target = new ArrayList<GoodsDO>();
    12         List<GoodsDO> orign = new ArrayList<GoodsDO>();
    13         for(int i = 1; i<3; i++) {
    14             GoodsDO p = new GoodsDO();
    15             p.setId(i);
    16             p.setName("ym" + i);
    17             target.add(p);
    18             
    19             p = new GoodsDO();
    20             p.setId(i - 1);
    21             p.setName("ym" + (i - 1));
    22             orign.add(p);
    23         }
    24         
    25         new  GoodsTempImpl().execute(target, orign);
    26 }
    View Code
  • 相关阅读:
    多层装饰器执行顺序
    flask之 中间件 蓝图 falsk请求上下文 rquirements.txt threading.local 偏函数
    flask 之 在flask中使用websocket
    flask 之项目分文件使用sqlalchemy+flask-migrate djagno多数据库
    flask之六 sqlachemy详解 scoped_session线程安全 基本增删改查 多对多关系建立和操作 flask-sqlalchemy的使用
    远程连接linux开发项目
    INT104-lab9
    INT104-lab8
    INT104-lab7
    Java-数据结构-泛型BST-CPT102-tutorial Week6
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/5518299.html
Copyright © 2020-2023  润新知