组合模式+访问者模式 实现商品多级目录分类

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

项目需求

商城有很多商品目录且层级很多。为了对层级目录进行管理需要满足对层级目录的增删

要求

  1. 层级目录是保存在DB的一旦项目进行初始化需要将层级目录设置为超热点缓存
  2. 支持在线对层及目录的增删
  3. 前端获取一次层及目录后每隔24小时对层级目录进行后台重新获取
  4. 层及目录更新需要先更新Redis缓存再更新DB后台层级目录缓存应该为永不过期缓存

实现方案

1.电商的存储结构

id        parentId        name

1                0                书籍

2                1                技术书籍

3                1                历史书籍

4                2                并发编程

5                2                设计模式       

6                3                二十四史         

2.当我们的项目进行初始化的时候就会将我们的DB里的这些目录进行查询转化为存储对象

3.将这个对象存储到我们的 Niginx 本地缓存并设置为永不过期

4.APP、页面进行调用的时候从Niginx 获取这份儿目录。并且 APP端进行缓存每隔 24小时进行一次标记位的访问 如果业务对我们的目录结构有增删标记位序号就会有所变化前端会再次对数据进行重新的同步

5.如果有修改后端是先修改缓存只针对缓存中需要修改的部分进行修改然后更新缓存目录层结构 + 标志位缓存更新成功后再更新DB

组合模式组成

  • component 抽象构件角色定义参加组合对象的共有方法和属性
  • leaf 叶子构件 叶子对象其下再也没有其它的分支也就是遍历的最小单位
  • composite 树枝构件树枝对象它的作用是组合树枝节点和叶子节点形成一个树形结构

访问者模式组成

表示一个作用于某对象结构中各个层级元素的操作它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作

  • vistor - 抽象访问者抽象类或者接口声明访问者可以访问哪些元素具体到程序中就是visit方法的参数定义哪些对象是可以被访问的
  • concreteVisitor- 具体到访问者他影响访问者访问到一个类之后怎么干要做什么事情
  • element-抽象元素抽口或者抽象类声明接收哪一类访问者访问程序上是通过accpet方法中的参数来定义的
  • concreteElement-具体元素实现accpet方法通常是vistor.vistor(this)基本上都形成一种模式了
  • ObjectStruture-结构对象

代码实现

/**
 * @author chongfayi
 */
public abstract class AbstractProductItem {
    public abstract void removeChild(AbstractProductItem item);
    public abstract void addChild(AbstractProductItem item);
}

/**
 * @author chongfayi
 */
@Data
public class ProductItem extends AbstractProductItem {

    /**
     * id
     */
    private int id;
    /**
     * 父id
     */
    private int pid;
    /**
     * 名称
     */
    private String name;
    /**
     * 叶子节点
     */
    private List<ProductItem> child = ListUtil.toList();

    @Override
    public void removeChild(AbstractProductItem item) {
        ProductItem productItem = (ProductItem) item;
        this.child = child.stream()
                .filter(x -> x.getId() != productItem.getId()).collect(Collectors.toList());
    }

    @Override
    public void addChild(AbstractProductItem item) {
        this.child.add((ProductItem) item);
    }
}


public interface ItemVisitor<T> {
    T visitor(ProductItem productItem);
}


@Component
public class AddItemVisitor implements ItemVisitor<ProductItem>{

    @Override
    public ProductItem visitor(ProductItem productItem) {
        // mock从缓存获取
        ProductItem currentItem = MockItem.item;
        if (productItem.getId() == currentItem.getId()){
            throw new UnsupportedOperationException("根节点不能删除");
        }
        if (productItem.getPid() == currentItem.getId()){
            currentItem.addChild(productItem);
            return currentItem;
        }
        addChild(productItem,currentItem);
        return currentItem;
    }

    private void addChild(ProductItem productItem, ProductItem currentItem) {
        for (ProductItem item : currentItem.getChild()) {
            if (item.getId() == productItem.getPid()){
                item.addChild(productItem);
                break;
            }else {
                addChild(productItem,item);
            }
        }
    }
}

@Component
public class DelItemVisitor implements ItemVisitor<ProductItem>{

    @Override
    public ProductItem visitor(ProductItem productItem) {
        // mock从缓存获取
        ProductItem currentItem = MockItem.item;
        if (productItem.getId() == currentItem.getId()){
            throw new UnsupportedOperationException("根节点不能删除");
        }
        if (productItem.getPid() == currentItem.getId()){
            currentItem.removeChild(productItem);
            return currentItem;
        }
        delChild(productItem,currentItem);
        return currentItem;
    }

    private void delChild(ProductItem productItem, ProductItem currentItem) {
        for (ProductItem item : currentItem.getChild()) {
            if (item.getId() == productItem.getPid()){
                item.removeChild(productItem);
                break;
            }else {
                delChild(productItem,item);
            }
        }
    }
}

public class MockItem {
    public static ProductItem item = new ProductItem();
    static{
        item.setId(1);
        item.setPid(0);
        item.setName("书籍");
        List<ProductItem> productItemList = new ArrayList<>();
        item.setChild(productItemList);
        ProductItem productItem = new ProductItem();
        productItem.setId(2);
        productItem.setPid(1);
        productItem.setName("技术书籍");
        productItemList.add(productItem);
        ProductItem productItem1 = new ProductItem();
        productItem1.setId(3);
        productItem1.setPid(1);
        productItem1.setName("历史书籍");
        productItemList.add(productItem1);

        List<ProductItem> productItemList2 = new ArrayList<>();
        ProductItem productItem4 = new ProductItem();
        productItem4.setId(6);
        productItem4.setPid(3);
        productItem4.setName("二十四史");
        productItemList2.add(productItem4);

        productItem1.setChild(productItemList2);

        List<ProductItem> productItemList1 = new ArrayList<>();
        ProductItem productItem2 = new ProductItem();
        productItem2.setId(4);
        productItem2.setPid(2);
        productItem2.setName("并发编程");
        ProductItem productItem3 = new ProductItem();
        productItem3.setId(5);
        productItem3.setPid(2);
        productItem3.setName("设计模式");
        productItemList1.add(productItem2);
        productItemList1.add(productItem3);
        productItem.setChild(productItemList1);



    }
}

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6