打造一个小超市

打造一个小超市


写这个小程序的目的

  • 熟悉面向接口编程
  • 熟悉面向对象模块知识

接口包

1.Card(卡)

package MyFirstSuperMarket;

/**
 * 定义卡的接口
 * 包含方法 processCardDiscount(计算卡使用中产生的优惠额度)
 * 包含参数 totalCost(产生优惠前的总消费额)
 *        totalCostAfterDiscount(折扣后的总消费额)
 *        Customer customer(传入的顾客参数)
 *        ShoppingCart shoppingCart(传入的顾客的购物车参数)
 */
public interface Card {
    double processCardDiscount(double totalCost, double totalCostAfterDiscount,
                               Customer customer, ShoppingCart shoppingCart);
}

2.Category(类别)

package MyFirstSuperMarket;

/**
 * 定义枚举类型 Category(种类)
 * 列举种类并赋值
 * 定义构造方法,提供最低价格和最高价格两个参数给枚举类型
 * 提供最低和最高价格的公有类获取和修改方法
 */
public enum Category {
    FOOD(10, 100),
    COOK(200, 2000),
    SNACK(5, 100),
    CLOTHES(200, 1000),
    ELECTRIC(200, 10000);


    int lowerPrice;
    int higherPrice;

    Category(int lowerPrice, int higherPrice) {
        this.lowerPrice = lowerPrice;
        this.higherPrice = higherPrice;
    }

    public int getLowerPrice() {
        return lowerPrice;
    }

    public void setLowerPrice(int lowerPrice) {
        this.lowerPrice = lowerPrice;
    }

    public int getHigherPrice() {
        return higherPrice;
    }

    public void setHigherPrice(int higherPrice) {
        this.higherPrice = higherPrice;
    }
}

3.Customer(顾客)

package MyFirstSuperMarket;

/**
 * 定义顾客接口
 * 实现获取顾客ID,定义购物开始初始化工作的方法(getCustID)
 * 定义顾客选择种类的方法(chooseCategory)
 * 定义购买商品的方法,并传参 buyMerchandise(商品)类型
 * 定义购买需要支付金额,传参购物车和总消费额,返回double类型支付额的方法(payFor)
 * 定义获取消费金额方法(getMoneySpent)
 * 定义检查顾客是否要去结账的方法(wantToCheckOut)
 */
public interface Customer {
    String getCustID();

    void startShopping();

    Category chooseCategory();

    int buyMerchandise(Merchandise merchandise);

    boolean wantToCheckOut();

    double payFor(ShoppingCart shoppingCart, double totalCost);

    double getMoneySpent();

}

4.DiscountStrategy(折扣策略)

package MyFirstSuperMarket;

/**
 * 定义打折策略接口
 * 实现打折方法(discount),并传参购物车
 */
public interface DiscountStrategy {
    double discount(ShoppingCart shoppingCart);
}

5.HasCard(是否有卡)

package MyFirstSuperMarket;

/**
 * 定义有卡的接口
 * 实现对有卡顾客获取卡的方法(getCard)
 */
public interface HasCard {
    Card getCard();
}

6.Market(超市)

package MyFirstSuperMarket;

/**
 * 定义超市接口
 * 暂无操作
 */
public interface Market {
}

7.Merchandise(商品)

package MyFirstSuperMarket;

/**
 * 定义商品接口
 * 实现商品相关数据的操作方法
 * 获取商品名字,售价,进阶,种类和库存
 * 定义购买方法 buy(传参购买数量)和购买失败后购物车内商品的放回操作 putBack(传参数量)
 */
public interface Merchandise {
    String getName();

    double getSoldPrice();

    double getPurchasePrice();

    int buy(int count);

    void putBack(int count);

    Category getCategory();

    int getCount();
}

8.Shopman(超市员工)

package MyFirstSuperMarket;

/**
 * 定义导购及超市工作人员接口
 * 实现服务顾客的操作并传参顾客
 */
public interface Shopman {
    void serveCustomer(Customer customer);
}

9.ShoppingCart(购物车)

package MyFirstSuperMarket;

import java.util.Date;

/**
 * 定义购物车类
 * 实现了商品的入购物车方法以及商品的总金额(未使用任何优惠前)并输出到控制台
 */
public class ShoppingCart {
    //合理将变量和方法访问控制符号设置为private
    //定义商品数组类型变量buy(即顾客放入购物车的商品)
    private Merchandise[] buy;
    //定义和buy相同下标的数组来记录相同下标下的buy的商品的数量
    private int[] count;
    //定义当前和最大变量来记录和控制购物车大小
    private int curr;
    private int max;

    /**
     * 构造方法,初始化购物车类
     * 传入参数 maxTypeToBuy(最多可以购买的商品种类)
     * 为 buy和 count初始化空间,数组大小为 maxTypeToBuy
     * 为 max 和 curr 赋初值
     * @param maxTypeToBuy 最多可以购买的商品的种类
     */
    public ShoppingCart(int maxTypeToBuy) {
        buy = new Merchandise[maxTypeToBuy];
        count = new int[maxTypeToBuy];
        max = maxTypeToBuy;
        curr = 0;
    }

    /**
     * 定义是否可以继续购入的方法
     * 比较当前和最大值的关系
     * @return 能否继续购入的布尔值
     */
    public boolean canHold() {
        return curr < max;
    }

    /**
     * 定义添加方法
     * @param m 要加入购物车的商品 m
     * @param countToBuy 要买 m 的数量
     * @return 添加是否成功的布尔值
     */
    public boolean add(Merchandise m, int countToBuy) {
        if (!canHold()) {
            return false;
        }
        buy[curr] = m;
        this.count[curr] = countToBuy;
        curr++;
        //m调用商品里的 buy 方法
        m.buy(countToBuy);
        return true;
    }

    /**
     * 定义计算商品原始价值的方法
     * 方便后续计算优惠策略后的金额
     * @return 返回购物车内的商品总价值
     */
    public double calculateOriginCost() {
        //定义局部变量 ret ,并初始化
        double ret = 0;
        //因为 pos++ 操作在判断和计算之前,所以初始化为-1,到执行第一次时刚好为零
        //pos为商品数组的编号
        int pos = -1;
        //遍历购物车的商品即buy数组,为空就continue,不为空就执行++操作
        //循环结束返回 ret
        for (Merchandise m :
                buy) {
            pos++;
            if (m == null) {
                continue;
            }
            ret += m.getPurchasePrice() * count[pos];
        }
        return ret;
    }

    /**
     * 覆盖Object类的toString方法
     * 实现购物信息到控制台的输出操作
     * @return 购物种类,数量,价格及总金额的输出
     */
    @Override
    public String toString() {
        //StringBuilder可以在sb被修改时在原对象上修改而不是新生成
        StringBuilder sb = new StringBuilder();
        sb.append("==================================\n");
        //Date类获取当前购物时间
        sb.append("购物时间:").append(new Date()).append("\n");
        int pos = -1;
        for (Merchandise m :
                buy) {
            pos++;
            if (m == null) {
                continue;
            }
            sb.append(m.getCategory().name()).append("\t").append(m.getName()).append("\t").append(count[pos])
                    .append("\t").append(m.getPurchasePrice() * count[pos]).append("\n");

        }
        sb.append("应付总金额为:").append(calculateOriginCost()).append("\n");
        sb.append("======================================");
        return sb.toString();
    }
}

10.SuperMarket(超市)

package MyFirstSuperMarket;

/**
 * 定义超市接口
 * 实现获取所有商品的方法 getAllMerchandise,类型为 Merchandise数组
 * 实现某种类别的商品随机获取,传参 category(商品类别)
 * 实现每日收入的汇总和销售日报的生成
 */
public interface SuperMarket {
    Merchandise[] getAllMerchandise();

    Merchandise[] getRandomMerchandiseOfCategory(Category category);

    void addEarnedMoney(double earnedMoney);

    void dailyReport();
}

接口实现包

1.AbsCustomer(抽象顾客类)

package impl;

import MyFirstSuperMarket.Category;
import MyFirstSuperMarket.Customer;
import MyFirstSuperMarket.Merchandise;
import MyFirstSuperMarket.ShoppingCart;

import static util.ShoppingUtil.getRandomCategory;

/**
 * 抽象类
 * 顾客的抽象类实现了顾客的接口
 * 实现顾客接口的所有方法
 */
public abstract class AbsCustomer implements Customer {
    //定义顾客本来打算买的东西的种类 shouldBuy,类型为Category
    private Category shouldBuy;
    //声明顾客ID,可以继续浏览的商品种类数量和当前已经浏览的商品种类的数量
    private String custID;
    private double moneySpent;
    private int guangLeft = 0;
    private int guangCount = 0;

    //定义静态且不可修改的变量,声明了可以逛的次数为5
    public static final int DEFAULT_GUANG_COUNT = 5;

    //多态实现构造方法,一个提供浏览逛的次数的设置,一个不提供
    public AbsCustomer(Category shouldBuy, String custID, int guangCount) {
        this.shouldBuy = shouldBuy;
        this.custID = custID;
        this.guangCount = guangCount;
    }

    public AbsCustomer(Category shouldBuy, String custID) {
        this.shouldBuy = shouldBuy;
        this.custID = custID;
    }

    //之后的都是一些实现接口和及自己的get/set方法
    public int getGuangCount() {
        return guangCount;
    }

    public void setGuangCount(int guangCount) {
        this.guangCount = guangCount;
    }

    public Category getShouldBuy() {
        return shouldBuy;
    }

    @Override
    public String getCustID() {
        return custID;
    }

    @Override
    //购物开始
    //将剩余的逛的次数置为初始值
    public void startShopping() {
        guangLeft = guangCount;
    }

    @Override
    //选择类型前先看必须买的,否则返回随机商品种类
    public Category chooseCategory() {
        //+1为了实现一开始就选择进入是否有想买的商品
        if (guangLeft + 1 >= guangCount) {
            return shouldBuy;
        } else {
            return getRandomCategory();
        }

    }


    @Override
    //执行到此步骤说明已经逛了一次之后,可以逛的剩余次数减一,返回布尔值
    //剩余次数小于等于零返回true,想要去结账
    public boolean wantToCheckOut() {
        guangLeft--;
        return guangLeft <= 0;
    }

    /**
     *在方法内实现顾客花费金额的累加
     * @param shoppingCart 购物车
     * @param totalCost 总价
     * @return返回总价即需要支付的钱
     */
    @Override
    public double payFor(ShoppingCart shoppingCart, double totalCost) {
        moneySpent += totalCost;
        return totalCost;
    }

    @Override
    public double getMoneySpent() {
        return moneySpent;
    }

}

2.CashCard(现金卡)

package impl;

import MyFirstSuperMarket.Card;
import MyFirstSuperMarket.Customer;
import MyFirstSuperMarket.ShoppingCart;

/**
 * 现金卡类
 * 实现接口 卡
 */
public class CashCard implements Card {
    private double point;

    public CashCard(double point) {
        this.point = point;
    }

    @Override
    /**
     * 声明方法 processCardDiscount ,传参总消费金额,折扣后总金额,顾客和对应的购物车
     * 返回优惠的金额
     */
    public double processCardDiscount(double totalCost, double totalCostAfterDiscount,
                                      Customer customer, ShoppingCart shoppingCart) {
        //现金卡大于待支付金额和小于待支付金额两种情况
        if (totalCostAfterDiscount < point) {
            point -= totalCostAfterDiscount;
            return totalCostAfterDiscount;
        } else {
            point = 0;
            return point;
        }
    }
}

3.SimpleMerchandise(简单商品)

package impl;

import MyFirstSuperMarket.Category;
import MyFirstSuperMarket.Merchandise;

/**
 * 简单的商品类
 * 实现商品接口
 */
public class SimpleMerchandise implements Merchandise {

    private String name;
    private double soldPrice;
    private double purchasePrice;
    private int count;
    private Category category;

    public SimpleMerchandise(String name, double soldPrice, double purchasePrice, int count, Category category) {
        this.name = name;
        this.soldPrice = soldPrice;
        this.purchasePrice = purchasePrice;
        this.count = count;
        this.category = category;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public double getSoldPrice() {
        return soldPrice;
    }

    @Override
    public double getPurchasePrice() {
        return purchasePrice;
    }

    @Override
    public int buy(int count) {
        this.count -= count;
        return count;
    }

    @Override
    public void putBack(int count) {
        this.count += count;
    }

    @Override
    public Category getCategory() {
        return category;
    }

    @Override
    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

4.SimpleShopMan(简单超市员工)

package impl;

import MyFirstSuperMarket.*;

import static util.ShoppingUtil.outPut;

/**
 * 简单超市服务员
 * 实现超市服务员接口
 * 从超市角度输出顾客购物清单,优惠金额和实付金额
 */
public class SimpleShopMan implements Shopman {

    private SuperMarket superMarket;

    public SimpleShopMan(SuperMarket superMarket) {
        this.superMarket = superMarket;
    }

    private static final int MAX_BUY_DEFAULT = 9;

    @Override
    /**
     * 服务顾客类
     */
    public void serveCustomer(Customer customer) {
        int maxTypeToBuy = MAX_BUY_DEFAULT;
        //强转检测合法性,为最大类型购买赋值为guangCount
        if (customer instanceof AbsCustomer) {
            maxTypeToBuy = ((AbsCustomer) customer).getGuangCount();
        }
        //为局部变量 shoppingCart new空间并传参顾客的最大逛商品数量给购物车的最大购买种类数量
        ShoppingCart shoppingCart = new ShoppingCart(maxTypeToBuy);
        customer.startShopping();
        //顾客不结账并且购物车可以放东西就执行循环
        //
        while ((!customer.wantToCheckOut()) && shoppingCart.canHold()) {
            Category category = customer.chooseCategory();
            if (category == null) {
                continue;
            }
            Merchandise[] toChoose = superMarket.getRandomMerchandiseOfCategory(category);
            for (Merchandise m : toChoose) {
                if (m == null) {
                    continue;
                }
                int buyCount = customer.buyMerchandise(m);
                if (buyCount > 0) {
                    shoppingCart.add(m, buyCount);
                    break;
                }
            }
        }
        double originCost = shoppingCart.calculateOriginCost();
        double finalCost = originCost;

        //判断是否有卡,并使用卡优惠
        double savedMoney = 0;
        if (customer instanceof HasCard) {
            Card card = ((HasCard) customer).getCard();
            savedMoney = card.processCardDiscount(originCost, finalCost, customer, shoppingCart);
            finalCost -= savedMoney;
        }

        double moneyEarned = customer.payFor(shoppingCart, finalCost);
        superMarket.addEarnedMoney(moneyEarned);

        outPut("顾客" + customer.getCustID() + "购物清单如下:");
        outPut(shoppingCart.toString());
        outPut("优惠金额为:" + savedMoney);
        outPut("实付金额为:" + moneyEarned);

    }


}

5.SimpleSuperMarket(简单超市)

package impl;

import MyFirstSuperMarket.Category;
import MyFirstSuperMarket.Merchandise;
import MyFirstSuperMarket.SuperMarket;

import static util.ShoppingUtil.outPut;

public class SimpleSuperMarket implements SuperMarket {

    private String name = "无名";
    private Merchandise[] all;
    private int[] allCount;
    private double totalMoneyEarn;
    private int customerCount;


    public SimpleSuperMarket(Merchandise[] all) {
        this.all = all;
        allCount = new int[all.length];
        for (int i = 0; i < all.length; i++) {
            allCount[i] = all[i].getCount();
        }
    }

    @Override
    public Merchandise[] getAllMerchandise() {
        return all;
    }

    @Override
    //在一定公式计算下概率为有无商品赋值,其余为空
    public Merchandise[] getRandomMerchandiseOfCategory(Category category) {
        Merchandise[] ret = new Merchandise[5];
        int pos = 0;
        for (Merchandise m :
                all) {
            //m的种类和category相同并且满足后面的条件,将其加入ret,pos++,寻找下一个category的商品
            if (m.getCategory() == category && Math.random() > 0.5 && pos < ret.length - 1) {
                ret[pos] = m;
                pos++;
            }
        }
        return ret;
    }

    @Override
    public void addEarnedMoney(double earnedMoney) {
        customerCount++;
        this.totalMoneyEarn += earnedMoney;
    }

    @Override
    public void dailyReport() {
        outPut("营业额为:" + totalMoneyEarn);
        outPut("商品售出情况如下:");
        for (int i = 0; i < all.length; i++) {
            if (allCount[i] != all[i].getCount()) {
                System.out.println(all[i].getCategory().name()
                        + "\t" + all[i].getName() + "\t" + (allCount[i] - all[i].getCount()));
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int[] getAllCount() {
        return allCount;
    }

    public void setAllCount(int[] allCount) {
        this.allCount = allCount;
    }
}

6.SuiYuanCustomer(随缘顾客)

package impl;

import MyFirstSuperMarket.Category;
import MyFirstSuperMarket.Merchandise;

/**
 * 抽象类必须被继承才可以使用
 * 随缘顾客继承可抽象顾客类
 */
public class SuiYuanCustomer extends AbsCustomer {
    public static final double MUST_BUY_CHANCE = 0.8;
    public static final double GUANG_BUY_CHANCE = 0.1;

    public SuiYuanCustomer(Category shouldBuy, String custID) {
        super(shouldBuy, custID, DEFAULT_GUANG_COUNT);
    }

    @Override
    //自己设计的一些是否购买的逻辑
    public int buyMerchandise(Merchandise merchandise) {
        //购买的几率
        double chanceToBuy = merchandise.getCategory() == getShouldBuy() ?
                MUST_BUY_CHANCE : GUANG_BUY_CHANCE;
        //购买的数量
        //即使是应该买的,也有可能购买数量为0
        if (chanceToBuy < Math.random()) {
            return 0;
        } else {
            return 1 + (int) (Math.random() * 3);
        }
    }
}

7.ThinkAndBuyCustomer(有购买需求的顾客)

package impl;

import MyFirstSuperMarket.Card;
import MyFirstSuperMarket.Category;
import MyFirstSuperMarket.HasCard;
import MyFirstSuperMarket.Merchandise;

/**
 * 知道自己要买什么的顾客
 * 继承抽象顾客类并且实现有卡的接口
 */
public class ThinkAndBuyCustomer extends AbsCustomer implements HasCard {

    private Card card = VIPCard.Level2;

    public ThinkAndBuyCustomer(Category shouldBuy, String custID) {
        super(shouldBuy, custID, DEFAULT_GUANG_COUNT);
    }

    @Override
    //符合自己购买需求的商品类返回购买数量1
    //不符合的取商品售价和该种类商品中间价为作比较再返回值
    public int buyMerchandise(Merchandise merchandise) {
        Category category = merchandise.getCategory();
        if (category == getShouldBuy()) {
            return 1;
        }
        double soldPrice = merchandise.getSoldPrice();
        double avgPrice = (category.getHigherPrice() + category.getLowerPrice()) / 2;

        if (soldPrice < avgPrice) {
            return 1;
        } else {
            return 0;
        }
    }

    public void setCard(Card card) {
        this.card = card;
    }

    @Override
    public Card getCard() {
        return card;
    }
}


8.VIPCard(VIP卡)

package impl;

import MyFirstSuperMarket.Card;
import MyFirstSuperMarket.Customer;
import MyFirstSuperMarket.ShoppingCart;

/**
 * 枚举 VIP等级
 * 实现卡类接口
 * 覆盖卡使用后的折扣力度
 */
public enum VIPCard implements Card {
    Level0(1),
    Level1(0.99),
    Level2(0.95),
    Level3(0.9),
    Level4(0.85),
    Level5(0.8);

    private double discount;

    VIPCard(double discount) {
        this.discount = discount;
    }

    @Override
    public double processCardDiscount(double totalCost, double totalCostAfterDiscount,
                                      Customer customer, ShoppingCart shoppingCart) {
        return totalCostAfterDiscount * (1 - discount);
    }
}

超市工具包

1.ShoppingUtil(整合方法,额外方法类)

package util;

import MyFirstSuperMarket.Category;
import MyFirstSuperMarket.Customer;
import MyFirstSuperMarket.Merchandise;
import MyFirstSuperMarket.SuperMarket;
import impl.*;

import java.util.Scanner;

/**
 * 商品工具包类
 * 创造超市,顾客,卡
 */
public class ShoppingUtil {

    //将输入输出集合化,避免太多的输出语句
    private static final Scanner in = new Scanner(System.in);

    public static Scanner inPut() {
        return in;
    }

    public static void outPut(Object obj) {
        System.out.println(String.valueOf(obj));
    }

    public static SuperMarket createSupermarket() {
        int merchandisePerCategory = 10;
        Merchandise[] all = new Merchandise[Category.values().length * merchandisePerCategory];
        for (Category category : Category.values()) {
            for (int i = 0; i < merchandisePerCategory; i++) {

                double soldPrice = Math.random() * (category.getHigherPrice() - category.getLowerPrice())
                        + category.getLowerPrice();

                double purchasePrice = soldPrice * 0.7;

                all[category.ordinal() * merchandisePerCategory + i] = new SimpleMerchandise(
                        category.name() + i, soldPrice, purchasePrice, 200, category
                );
            }
        }

        SimpleSuperMarket superMarket = new SimpleSuperMarket(all);
        outPut("请输入超市的名字:");
        String s = inPut().next();
        if (s.trim().length() > 0) {
            superMarket.setName(s.trim());
        }
        return superMarket;
    }

    public static Customer createCustomer(boolean auto) {
        if (auto) {
            String custId = "CUST" + (int) (Math.random() * 10000);
            Category shouldBuy = getRandomCategory();
            if (Math.random() < 0.5) {
                return new SuiYuanCustomer(shouldBuy, custId);
            } else {
                ThinkAndBuyCustomer ret = new ThinkAndBuyCustomer(shouldBuy, custId);
                ret.setCard(getRandomVIPCard());
                return ret;
            }
        }
        return null;

    }


    public static Category getRandomCategory() {
        return Category.values()[(int) (Math.random() * 1000) % Category.values().length];
    }

    public static VIPCard getRandomVIPCard() {
        return VIPCard.values()[(int) (Math.random() * 1000) % VIPCard.values().length];
    }
}

程序运行

1.ShoppingAPP(main函数)

import MyFirstSuperMarket.Customer;
import MyFirstSuperMarket.Shopman;
import MyFirstSuperMarket.SuperMarket;
import impl.SimpleShopMan;

import static util.ShoppingUtil.*;

public class ShoppingAPP {
    public static void main(String[] args) {
        SuperMarket superMarket = createSupermarket();

        Shopman shopman = new SimpleShopMan(superMarket);

        boolean open = true;
        while (open) {
            //开业后启用超市员工
            new ShoppingTask(shopman).executeTask();
            outPut("是否继续营业?(YES)");
            open = !inPut().next().trim().equalsIgnoreCase("no");
        }
        superMarket.dailyReport();
    }

}

class ShoppingTask {
    private Shopman shopman;

    public ShoppingTask(Shopman shopman) {
        this.shopman = shopman;
    }

    public void executeTask() {
        Customer customer = createCustomer(true);
        shopman.serveCustomer(customer);
    }
}

总 结


  • 接口提供规范,方法名。方法体由实现接口的类覆盖实现
  • 抽象类中的方法只能被继承,然后被子类对象调用
  • 调用接口的方法必须实现接口中全部的方法
  • 抽象类的用法是为了实现接口(大部分)
  • 抽象方法和抽象类一样都不可以被直接调用,抽象方法可以被覆盖使用(用于不想让子类直接使用父类的方法,而是让其通过覆盖使用)
  • 抽象类不一定包含抽象方法,包含抽象方法的类一定是抽象类
  • 抽象方法中的抽象方法不一定要全部被实现,只需要实现有用的即可
  • 保持包内的神秘性,合理使用访问限定修饰符 private
  • 如果父类没有无参构造方法,子类构造方法要调用父类构造方法,且置于第一行
  • hashCode和equals方法需要被覆盖才有用
  • 1.若重写了equals(Object obj)方法,则有必要重写hashCode()方法。
    2.若两个对象equals(Object obj)返回true,则hashCode()有必要也返回相同的int数。
    3.若两个对象equals(Object obj)返回false,则hashCode()不一定返回不同的int数。
    4.若两个对象hashCode()返回相同int数,则equals(Object obj)不一定返回true。
    5.若两个对象hashCode()返回不同int数,则equals(Object obj)一定返回false。
  • 反射可以实现private方法和变量的调用
  • 通过在特定工具包实现方法来避免重复性操作。eg:通过在util包实现output和input来避免大篇幅的输入输出操作
  • 接口中在JDK8中可以有default和静态方法,不需要其他类实现
  • 接口只是定义规范,具体业务实现需要定义相关的类去实现接口来完成,最后统一调度

后续还会优化
待更新

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值