Это 4-й день моего участия в ноябрьском испытании обновлений, подробности о мероприятии:Вызов последнего обновления 2021 г.
Эта статья взята из статьи «Вот как следует изучать шаблоны проектирования».
1. Используйте режим стратегии, чтобы реализовать выбор рекламных предложений.
Как мы все знаем, курсы архитекторов Академии Гупао часто имеют льготные мероприятия, и есть много возможностей для льготных стратегий, таких как получение купонов на отчисления, акции с кэшбэком, групповые скидки и т. д. Следующий код используется для имитации, сначала создайте абстрактную PromotionStrategy стратегии продвижения.
/**
* 促销策略抽象
* Created by Tom.
*/
public interface IPromotionStrategy {
void doPromotion();
}
Затем создайте класс CouponStrategy для стратегии вычета купонов, класс CashbackStrategy для стратегии поощрения возврата наличных, класс GroupbuyStrategy для стратегии групповых скидок и класс EmptyStrategy для стратегии без скидок. Код для класса CouponStrategy выглядит следующим образом.
public class CouponStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("使用优惠券抵扣");
}
}
Код класса CashbackStrategy выглядит следующим образом.
public class CashbackStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("返现,直接打款到支付宝账号");
}
}
Код для класса GroupbuyStrategy выглядит следующим образом.
public class GroupbuyStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("5人成团,可以优惠");
}
}
Код для класса EmptyStrategy выглядит следующим образом.
public class EmptyStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("无优惠");
}
}
Затем создайте класс PromotionActivity для плана продвижения.
public class PromotionActivity {
private IPromotionStrategy strategy;
public PromotionActivity(IPromotionStrategy strategy) {
this.strategy = strategy;
}
public void execute(){
strategy.doPromotion();
}
}
Наконец, напишите тестовый код клиента.
public static void main(String[] args) {
PromotionActivity activity618 = new PromotionActivity(new CouponStrategy());
PromotionActivity activity1111 = new PromotionActivity(new CashbackStrategy());
activity618.execute();
activity1111.execute();
}
На этом этапе друзья обнаружат, что нецелесообразно помещать приведенный выше тестовый код на стороне клиента в реальный бизнес-сценарий. Потому что, когда мы проводим мероприятия, нам часто нужно динамически выбирать стратегии продвижения в соответствии с различными потребностями, и мы не будем реализовывать несколько скидок одновременно. Поэтому код обычно пишется так.
public static void main(String[] args) {
PromotionActivity promotionActivity = null;
String promotionKey = "COUPON";
if(StringUtils.equals(promotionKey,"COUPON")){
promotionActivity = new PromotionActivity(new CouponStrategy());
}else if(StringUtils.equals(promotionKey,"CASHBACK")){
promotionActivity = new PromotionActivity(new CashbackStrategy());
}//......
promotionActivity.execute();
}
После этого преобразования код соответствует потребностям бизнеса, и клиенты могут выбирать различные предпочтительные стратегии в соответствии со своими потребностями. Однако после периода накопления бизнеса будет все больше и больше рекламных мероприятий. В результате программисты стали часто работать сверхурочно, меняя код в одночасье перед каждым событием и проводя повторные тесты, логика суждений может усложняться. На этом этапе нам нужно подумать о том, нуждается ли код в рефакторинге. Оглядываясь назад на шаблоны проектирования, которые мы изучили раньше, как мы должны оптимизировать этот код? На самом деле класс PromotionStrategyFactory можно создать, объединив шаблон singleton и простой шаблон factory.
public class PromotionStrategyFacory {
private static Map<String,IPromotionStrategy> PROMOTIONS = new HashMap<String, IPromotionStrategy>();
static {
PROMOTIONS.put(PromotionKey.COUPON,new CouponStrategy());
PROMOTIONS.put(PromotionKey.CASHBACK,new CashbackStrategy());
PROMOTIONS.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
}
private static final IPromotionStrategy EMPTY = new EmptyStrategy();
private PromotionStrategyFacory(){}
public static IPromotionStrategy getPromotionStrategy(String promotionKey){
IPromotionStrategy strategy = PROMOTIONS.get(promotionKey);
return strategy == null ? EMPTY : strategy;
}
private interface PromotionKey{
String COUPON = "COUPON";
String CASHBACK = "CASHBACK";
String GROUPBUY = "GROUPBUY";
}
public static Set<String> getPromotionKeys(){
return PROMOTIONS.keySet();
}
}
На данный момент тестовый код клиента выглядит следующим образом.
public static void main(String[] args) {
PromotionStrategyFacory.getPromotionKeys();
String promotionKey = "COUPON";
IPromotionStrategy promotionStrategy = PromotionStrategyFacory.getPromotionStrategy (promotionKey);
promotionStrategy.doPromotion();
}
После того, как код оптимизирован, работа программиста по обслуживанию становится проще. Каждое новое действие не влияет на исходную логику кода.
2 Воспользуйтесь режимом стратегии, чтобы воссоздать сценарий выбора способа оплаты.
Чтобы углубить наше понимание паттерна стратегии, давайте рассмотрим другой случай. Я считаю, что все вы использовали Alipay, WeChat Pay, UnionPay и Jingdong Baitiao.Распространенный сценарий применения заключается в том, что когда вы размещаете заказ на оплату, вам будет предложено выбрать способ оплаты.Если пользователь не выберет его, система по умолчанию выберет рекомендуемый способ оплаты. Глядя на диаграмму классов, показанную на рисунке ниже, мы используем шаблон стратегии для моделирования этого бизнес-сценария.
Сначала создайте абстрактный класс Payment, определите спецификацию платежа и логику платежа, код выглядит следующим образом.
import com.tom.pattern.strategy.pay.PayState;
/**
* 支付渠道
* Created by Tom.
*/
public abstract class Payment {
public abstract String getName();
//通用逻辑被放到抽象类里实现
public MsgResult pay(String uid, double amount){
//余额是否足够
if(queryBalance(uid) < amount){
return new MsgResult(500,"支付失败","余额不足");
}
return new MsgResult(200,"支付成功","支付金额" + amount);
}
protected abstract double queryBalance(String uid);
}
Затем создайте конкретные способы оплаты соответственно.Код класса AliPay выглядит следующим образом.
public class AliPay extends Payment {
public String getName() {
return "支付宝";
}
protected double queryBalance(String uid) {
return 900;
}
}
Код класса JDPay Jingdong Baitiao выглядит следующим образом.
public class JDPay extends Payment {
public String getName() {
return "京东白条";
}
protected double queryBalance(String uid) {
return 500;
}
}
Код класса оплаты WeChat WechatPay выглядит следующим образом.
public class WechatPay extends Payment {
public String getName() {
return "微信支付";
}
protected double queryBalance(String uid) {
return 263;
}
}
Код для платежа UnionPay класса UnionPay выглядит следующим образом.
public class UnionPay extends Payment {
public String getName() {
return "银联支付";
}
protected double queryBalance(String uid) {
return 120;
}
}
Затем создайте класс-оболочку MsgResult для статуса платежа.
/**
* 支付完成以后的状态
* Created by Tom.
*/
public class MsgResult {
private int code;
private Object data;
private String msg;
public MsgResult(int code, String msg, Object data) {
this.code = code;
this.data = data;
this.msg = msg;
}
@Override
public String toString() {
return "MsgResult{" +
"code=" + code +
", data=" + data +
", msg='" + msg + '\'' +
'}';
}
}
Создайте класс управления платежной политикой.
import java.util.HashMap;
import java.util.Map;
/**
* 支付策略管理
* Created by Tom.
*/
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String JD_PAY = "JdPay";
public static final String WECHAT_PAY = "WechatPay";
public static final String UNION_PAY = "UnionPay";
public static final String DEFAULT_PAY = ALI_PAY;
private static Map<String,Payment> strategy = new HashMap<String,Payment>();
static {
strategy.put(ALI_PAY,new AliPay());
strategy.put(JD_PAY,new JDPay());
strategy.put(WECHAT_PAY,new WechatPay());
strategy.put(UNION_PAY,new UnionPay());
}
public static Payment get(String payKey){
if(!strategy.containsKey(payKey)){
return strategy.get(DEFAULT_PAY);
}
return strategy.get(payKey);
}
}
Создайте класс Заказ.
import com.tom.pattern.strategy.pay.payport.PayStrategy;
import com.tom.pattern.strategy.pay.payport.Payment;
/**
* Created by Tom.
*/
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public MsgResult pay(){
return pay(PayStrategy.DEFAULT_PAY);
}
public MsgResult pay(String payKey){
Payment payment = PayStrategy.get(payKey);
System.out.println("欢迎使用" + payment.getName());
System.out.println("本次交易金额为" + amount + ",开始扣款");
return payment.pay(uid,amount);
}
}
Наконец, напишите тестовый код клиента.
public static void main(String[] args) {
Order order = new Order("1","2020031401000323",324.5);
System.out.println(order.pay(PayStrategy.ALI_PAY));
}
Результат работы показан на рисунке ниже.
Я надеюсь, что благодаря примерам распространенных бизнес-сценариев друзья смогут лучше понять модель стратегии.
Следуйте «Архитектуре Тома» и ответьте на «Шаблон проектирования», чтобы получить полный исходный код.
Эта статья является оригиналом "Архитектуры бомбы Тома", пожалуйста, указывайте источник при перепечатке. Технология заключается в обмене, я разделяю свое счастье! Если эта статья полезна для вас, пожалуйста, подпишитесь и поставьте лайк, если у вас есть какие-либо предложения, вы также можете оставить комментарий или личное сообщение Ваша поддержка является движущей силой для меня, чтобы продолжать творить. Обратите внимание на «архитектуру бомбы Тома», чтобы получить больше технической галантереи!