アプリケーションシナリオ
JD.com、Tmall Double Eleven、バレンタインデーの商品プロモーション、さまざまな商品にはさまざまなプロモーション活動があります
- 完全削減:完全200マイナス50
- すべての完全な控除:すべての完全な100マイナス10
- 割引:2アイテムで20%オフ、3アイテムで30%オフ
- 数量マイナス:フル3個マイナス最低価格1個
顧客は注文時に手を切るためにそれらのいくつかを選択できます。バックエンドはどのように柔軟に金額の計算に対処できますか?将来、さまざまなフェスティバルでより多くのプロモーションが行われる可能性があります。注文金額の計算方法?
簡単な実装例
public class OrderService {
public Order OrderPrices(Order order, String promotion) {
if (promotion.equals("promotion-1")) {
//计算金额
} else if (promotion.equals("promotion-2")) {
//计算金额
}
switch (promotion) {
case "promotion-1" :
//计算金额
break;
case "promotion-2" :
//计算金额
break;
}
return order;
}
}
上記のようにifelseやswitchcaseを使用しても問題ありませんが、さまざまなプロモーション活動があります。この場合、if elseやswitchcaseのコンテンツが多いので、どうすれば改善
できるのでしょうか。それぞれのプロモーション方法は、この方法の設計原則である単一責任の原則に基づいて、別々に実行するとより良いものになります。
public class OrderService {
public Order OrderPrices(Order order, String promotion) {
if (promotion.equals("promotion-1")) {
calPromotion1(order);
} else if (promotion.equals("promotion-2")) {
calPromotion2(order);
}
switch (promotion) {
case "promotion-1" :
calPromotion1(order);
break;
case "promotion-2" :
calPromotion2(order);
break;
}
return order;
}
public Order calPromotion1(Order order) {
return order;
}
public Order calPromotion2(Order order) {
return order;
}
}
上記の改善はより良いものですが、プロモーション活動は絶えず変化しており、変更が行われたらすぐにOrderServiceクラスを変更する必要があります。OrderServiceクラスは注文に関するものであり、変更を少なくしたいと考えています。絶えず変化しているのは
分析です。プロモーションアルゴリズムの。何ここで変更されていることは同じ動作のために別のアルゴリズムであるので、再びそれを改善
コードを改善する
同じ動作に対して異なるアルゴリズムを実装するために、インターフェイスを使用して動作を定義し、異なるアルゴリズムを使用してインターフェイスを個別に実装できます。
設計原則:変更のために閉じ、拡張のために開く
public interface PromotionAlgorithm {
Order promotionAlgorithm(Order order);
}
public class PromotionAlgorithm1 implements PromotionAlgorithm {
@Override
public Order promotionAlgorithm(Order order) {
System.out.println("满200减50");
return order;
}
}
public class PromotionAlgorithm2 implements PromotionAlgorithm {
@Override
public Order promotionAlgorithm(Order order) {
System.out.println("满2件打8折");
return order;
}
}
public class OrderService {
public Order OrderPrices(Order order, String promotion) {
if (promotion.equals("promotion-1")) {
return new PromotionAlgorithm1().promotionAlgorithm(order);
} else if (promotion.equals("promotion-2")) {
return new PromotionAlgorithm2().promotionAlgorithm(order);
}
switch (promotion) {
case "promotion-1" :
return new PromotionAlgorithm1().promotionAlgorithm(order);
case "promotion-2" :
return new PromotionAlgorithm2().promotionAlgorithm(order);
}
return order;
}
}
各プロモーションアルゴリズムを個別に実装して使用します。これは
、戦略パターンのアプリケーションクラス図です。
戦略モード
定義
ストラテジーモードは、一連のアルゴリズムを定義し、各アルゴリズムをカプセル化し、それらを相互に置き換えることができるため、アルゴリズムは、それを使用するユーザーとは無関係に変更できます。
意図
一連のアルゴリズムを定義し、それらを1つずつカプセル化し、互換性を持たせる
主に問題を解決する
複数の同様のアルゴリズムの場合、if ... elseの使用は複雑であり、維持するのが困難です。
いつ使用するか
システムには多くのクラスがあり、それらを区別するのはそれらの直接的な動作です
長所と短所
利点:
1:さまざまなアルゴリズムを自由に切り替えることができます
2:複数の判断を使用することによって引き起こされるトラブルを回避できます
3:優れたスケーラビリティ
短所:
1:より多くの戦略クラスがあります
。2:すべての戦略クラスを外の世界に公開する必要があります。
以下のクラス図を見てみましょう。
関連する役割:
- コンテキストロール:Stratogyクラスへの参照を保持する
- 抽象戦略(Strategy)ロール:これは抽象ロールであり、通常はインターフェイスまたは抽象クラスによって実装されます。このロールは、特定のストラテジークラスに必要なすべてのインターフェイスを提供します。
- 特定の戦略(ConcreteStartegy)の役割:関連するアルゴリズムまたは動作のパッケージ化
コンテキストクラス:
public class Context {
private Strategy strategy;
/** 策略方法 */
public void contextInterface() {
strategy.strategyInterface();
}
}
戦略クラス:
public interface Strategy {
/** 策略方法 */
void strategyInterface();
}
ConcreteStrategyクラス:
public class ConcreteStrategy implements Strategy{
/** 策略方法 */
@Override
public void strategyInterface() {
//do something
}
}
諸葛亮の秘訣
当時、趙雲が劉備を劉備に守って美女と結婚させたとき、諸葛亮は彼に3つの秘訣と3つの秘訣を与え、趙雲に状況に応じて行動するように頼んだ。これらの3つのヒントとコツは、戦略モードに沿ったものです。諸葛亮は戦略モードの開始者ではなく、元の開業医でもあるようです。以下は小さな例です。
ヒントとコツのインターフェイス:
public interface SeminalVesicle {
/** 按计行事 */
String tricks();
}
計画の実装クラスに従って実行します。
public class BackDoor implements SeminalVesicle {
/** 按计行事 */
@Override
public String tricks() {
return "走乔国老的后门";
}
}
public class GoBack implements SeminalVesicle {
/** 按计行事 */
@Override
public String tricks() {
return "骗刘备回去";
}
}
public class Retreat implements SeminalVesicle {
/** 按计行事 */
@Override
public String tricks() {
return "请孙夫人退兵";
}
}
趙雲クラス:
public class ZhaoYun {
private SeminalVesicle seminalVesicle;
public ZhaoYun(SeminalVesicle seminalVesicle) {
this.seminalVesicle = seminalVesicle;
}
/** 按计行事 */
public String act() {
return seminalVesicle.tricks();
}
}
テストカテゴリ:
public class Test {
public static void main(String[] args) {
ZhaoYun zhaoYun = new ZhaoYun(new Retreat());
System.out.println("赵云按计行事");
System.out.println(zhaoYun.act());
}
}
クラス図:
戦略が4つを超える場合は、戦略の拡張を回避するために混合モードの使用を検討する必要があることに注意してください。