1.はじめに
1.1 LOL 4件のトランジット強盗
「トリック」
2016年世界大会では、ROXの一族戦争G2チームは、ROXは、チームメイトが最初に開いたグループだったときSEMBは、ケナンを使用するシングルプレイヤーに、開いているグループSEMBは、大規模な爆発ヒット傷を使用してストロークをバックハンド直接ゲームの終わり。
「火」
2015年世界大会で、EDG IG藩の藩戦争、前バレルで、川で4の波を茂みに隠された樽を爆破するドラゴン、EDGシングルポーンキャプテン一般的な使用、2つの紛争当事者ショットブラストダメージを操作し、IGチームは、すべて不自由。
「忘却」
2017 LPLコンテスト、EDG OMG一族の戦争の一族、双方がビジョンを競う、OMG AのEDGは、単一のワニの復活を打つ、彼が追求を促進したいと考えています。そして、ADC OMGの選手Smlzは4が殺さ5をスプレー再帰利用の口を光りました。
「ソアリング」
2017 LCKコンテストでは、SKT KT一族の戦争の一族。KTのチームはちょうど係合から巨大な龍をキックダウン、単一偽物SKTバネの使用は、青バフ、大4で大きな動きが光りました。KT天国は4に直接送信しました。
伝説のリーグの人民代表大会は、これらの古典的な戦闘群を聞いたことが分かり、シーンの名の下に確認します。そして後には、単一のIG TheShyの「剣」、その上の「地すべり」とのRNG単一Letmeを拡張しました。トランジット強盗にランクされ、単独で状況を開いた英雄を使用するプレイヤーに依存すると言うことができます。ここでは、主要な戦争の大規模なグループ、より多くのプレイヤーによって精神的なプレー、フラッシュ+スキル、戦闘群を勝ち取る出力に追いつくための最初の波ヒットまたは傷つけ、彼のチームメイトの完璧なコントロールです。
数多くの英雄のリーグは、各英雄は4つのヒーローのスキルを持っています。短時間でテンキー英雄の連隊、スキルの数十を果たしますが、ヒーローのスキルの多くは、このようなノック、撃退、石油化学および他の同様の抑制効果、持っている。これらのアルゴリズムをそれぞれのスキルのリリースの場合ヒーローは別のアルゴリズムを使用する必要があり、この方法は喜ん冗長、および維持するのが困難になります。
冗長な擬似コードを示します。
public class HeroContext {
public void releaseSkill(Hero hero) {
if (heroType == 1) {
if (skillType == 1) {
// 算法:类型为1的英雄释放1技能
} else if (skillType == 2) {
// 算法:类型为1的英雄释放2技能
} else if (skillType == 3) {
// 算法:类型为1的英雄释放3技能
}
} else if(heroType == 2) {
// 算法
...
} else if(heroType == 3) {
// 算法
...
} else {...}
}
}
1.2戦略モードは、オブジェクトの行動パターンです
Strategyパターンは、より容易に、クライアントプログラムのアルゴリズムより複雑なコード、貧しいスケーラビリティに含まれ、デザインモードで理解することができます。このアルゴリズムは、プログラムがあり、ビジネスの多数のための実現可能であるならば、我々は同じブロック方式を維持し、問題はより深刻で、望ましいことではありません。
異なる実装クラスを達成するために異なる戦略を呼び出すようにするために私たちは、実装するための別のクラスとして、異なるアルゴリズムを引き抜きます。一方、モデルが実装され、複数の政策の一貫性を確保するために、抽象クラスの戦略を提供します。それがクライアントのためである、あなたは異なる戦略を交換することができ、さまざまな戦略を起動する場合と同じ入り口を使用することができます。これは、クライアントのアルゴリズム独立したが、あなたは別の維持することができ、および任意のポリシーの実装に拡張することができます。
簡単に言え、またはオブジェクト指向開発ではなく、プロセス指向開発。特定のポリシーオブジェクトとしてアルゴリズムアプローチ。目的を達成するために異なる戦略を呼び出すことにより、クライアントの方法、代わりのプログラムの期間中に書かれた複数のアルゴリズム。
2.なぜ戦略パターンの紹介です
環境クラスは、統一されたコールにする方法を提供し、指定された異なる; Strategyパターンは、発信者が特定の実装に焦点を当てていない、アルゴリズムが異なるアルゴリズムが異なる戦略クラスによって達成することができる分離し、ポリシーパッケージの種類の異なるアルゴリズムを分離することです戦略は異なるアルゴリズムに内部戦略を実行することができます。
環境方針モードはAbstractStrategyから抽象クラスから重合StrategyContext、環境方針を、環境の統一ポリシークラスの特定のメソッドアルゴリズム()の呼び出しのアルゴリズム()を提供します。特定のポリシークラスの実績は、内部アルゴリズムアルゴリズム()のために責任があります。
使用戦略モード3.どのような状況
- あなたが別の具体的な実装を使用したい行動の異なるタイプのために、あなたは、Strategyパターンの最適化を使用することができます。
- より複雑なケース文のコードブロックでは、ポリシーモデルを最適化するために使用することができる、他の場合には低品質のプログラムを最適化するために使用することができます。
4. Strategyパターンの実装
4.1実装:抽象クラス継承+
4.1.1役割の
伝統的な戦略モデルの役割は、次のとおりです。環境、抽象戦略クラス、具体的な戦略クラスを。
具体的な戦略クラスは抽象クラス戦略、異なる戦略アルゴリズムを達成するための別の具体的な戦略を継承します。抽象的で環境戦略の間の集約関係です。
図クラス4.1.2
4.1.3コードの実装
- AbstractStrategy.java
/** 抽象策略类 */
public abstract class AbstractStrategy {
public abstract void algorithm();
}
- ConcreteStrategyA.java
/** 具体策略类 */
public class ConcreteStrategyA extends AbstractStrategy {
/* 抽象方法实现算法 */
public void algorithm() {
// 算法A
System.out.println("策略实现方法");
}
}
- Context.java
/** 策略环境类 */
public class Context {
private AbstractStrategy strategy;
/* 抽象方法实现算法 */
public void setStrategy(AbstractStrategy strategy) {
this.strategy = strategy;
}
/* 环境类统一实现策略方法 */
public void algorithm() {
strategy.algorithm();
}
}
4.2実装:インターフェイスおよび組成
4.2.1ロール
インタフェース+組み合わされた実装形態の役割は次のとおり環境政策インタフェース、インタフェースの実装。
ポリシーと実装クラス間の関係の政策・インターフェースは、特定の戦略アルゴリズムを達成するため、実装されています。環境と政策との間のインタフェースは、集約関係です。
インタフェース合わせた交換連続の使用の二つの方法の差は、なるようJava開発仕様は継承の誤用を回避するために、あるいは継承の組み合わせを使用することを提案、そしてもちろん、上記の例が悪用されません。継承は関係「-IS」されていることの本質的な違いとの組み合わせでの継承、組み合わせは「HAS-A」の関係です。クラスから、図1に見ることができる。環境的文脈が使用されるポリマーである(組み合わせ)の関係。
図クラス4.2.2
4.2.3コードの実装
- IStrategy.java
/** 抽象策略类 */
public interface IStrategy {
public abstract void algorithm();
}
- ConcreteStrategyAImpl.java
/** 具体策略类 */
public class ConcreteStrategyAImpl implements IStrategy {
/* 抽象方法实现算法 */
public void algorithm() {
// 算法A
System.out.println("策略实现方法");
}
}
- Context.java
/** 策略环境类 */
public class Context {
private IStrategy strategy;
/* 抽象方法实现算法 */
public void setStrategy(IStrategy strategy) {
this.strategy = strategy;
}
/* 环境类统一实现策略方法 */
public void algorithm() {
strategy.algorithm();
}
}
5. Strategyパターンの例
5.1デモ命令
栄光の王はほぼ4年ぶり、そしてより多くの英雄、より多くのスキルを超えヒョンました。しかし、効果はまだリーグのスキル効果(通過)と(コピー)に沿ってスキルです。コモンコントロールはとてもハードノック、めまい、石油化学、冷凍し、嘲笑など、スローダウンなどのソフトコントロール、弱体化が含まれます。制御とオープングループのためのハード、ソフト、対照群には、人々を守るために戦うために、完璧な波が大規模なグループの戦いは、コントロールの波によって開かれ始めました。
ここでは、主人公のスキルは抽象オブジェクト、スキルを解放する方法を提供する抽象戦略インタフェースなどのオブジェクトの振る舞いを制御するために、異なる制御実装クラスの効果のために異なる戦略を使用して、実装クラスを実現完全な制御効果を担当しています。
5.2デモクラス図
5.3デモのサンプルコード
(1)新しいスキル戦略インターフェースの効果
- HeroSkillStrategyの.java
/**
* @className: HeroSkillStrategy
* @description: (抽象策略)抽象英雄技能
* 此处使用接口+组合的方式替换抽象类+继承;
* 组合遵循“has a”的思想,继承遵循“is a”的思想;
* 抽象类与具体类之间有严格的继承关系,遵循“is a”的思想;
* @author: niaonao
* @date: 2019/9/26
**/
public interface HeroSkillStrategy {
/** 发动技能 */
void releaseSkill();
}
(2)環境のリリースのスキルは、
環境HeroContext.javaをトリガースキルを作成します
- HeroContext.java
/**
* @className: HeroContext
* @description: 策略使用者环境
* @author: niaonao
* @date: 2019/9/26
**/
public class HeroContext {
/** 技能策略 */
private HeroSkillStrategy heroSkillStrategy;
public void setSkill(HeroSkillStrategy heroSkillStrategy) {
this.heroSkillStrategy = heroSkillStrategy;
};
/**
* 释放技能
*/
public void releaseSkill() {
heroSkillStrategy.releaseSkill();
}
}
(3)実装クラスのコントロールのスキル
- 新建减速效果实现类DecelerateStrategy.java
- 新建冰冻效果实现类FreezeStrategy.java
- 新建石化效果实现类PetrifyStrategy.java
- 新建击飞效果实现类SmiteStrategy.java
- 新建眩晕效果实现类StunStrategy.java
- 新建压制效果实现类SuppressStrategy.java
- 新建嘲讽效果实现类TauntStrategy.java
import lombok.extern.slf4j.Slf4j;
/**
* @className: DecelerateStrategy
* @description: (具体策略)减速技能
* @author: niaonao
* @date: 2019/9/26
**/
@Slf4j
public class DecelerateStrategy implements HeroSkillStrategy {
/** 减速策略实现 */
@Override
public void releaseSkill() {
// 策略具体算法
log.info("减速留住敌方前排,双C伤害很高,前排被击杀了,这波大龙要放掉了!\n");
}
}
/** (具体策略)冰冻技能 */
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FreezeStrategy implements HeroSkillStrategy {
/** 冰冻策略实现 */
@Override
public void releaseSkill() {
// 策略具体算法
log.info(" --> 冰冻前排,双C伤害很高,前排被打残,这波大龙要放掉了!\n");
}
}
/** (具体策略)石化技能 */
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class PetrifyStrategy implements HeroSkillStrategy {
/** 石化策略实现 */
@Override
public void releaseSkill() {
// 策略具体算法
log.info(" --> 石化鲁班,ad瞬间融化,敌方战术性放掉暴君!\n");
}
}
/** @description: (具体策略)击飞技能 */
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SmiteStrategy implements HeroSkillStrategy {
/** 击飞策略实现 */
@Override
public void releaseSkill() {
// 策略具体算法
log.info(" --> 击飞五人,双C跟上输出,打出团灭,顺势拿下大龙!\n");
}
}
/** 眩晕技能 */
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class StunStrategy implements HeroSkillStrategy {
/** 眩晕策略实现 */
@Override
public void releaseSkill() {
// 策略具体算法
log.info(" --> 眩晕三人,一波完美高地团战,攻破敌方水晶!\n");
}
}
/** 压制技能 */
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SuppressStrategy implements HeroSkillStrategy {
/** 压制策略实现 */
@Override
public void releaseSkill() {
// 策略具体算法
log.info(" --> 压制一诺赵云,直接控到死,一诺没有办法啊!\n");
}
}
/** 嘲讽或沉默技能 */
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TauntStrategy implements HeroSkillStrategy {
/** 嘲讽策略实现 */
@Override
public void releaseSkill() {
// 策略具体算法
log.info(" --> 闪现嘲讽姜子牙,瞬间融化,这波可以直接上高地!\n");
}
}
(4) 模拟客户端程序
创建策略环境类测试,模拟客户端使用策略。
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
/**
* @className: HeroSkillTests
* @description: 测试
* @author: niaonao
* @date: 2019/9/26
**/
@Slf4j
public class HeroSkillTests {
private static List<String> SuppressHeroList = Arrays.asList("东皇太一", "张良");
private static List<String> TauntHeroList = Arrays.asList("白起", "司马懿", "花木兰");
private static List<String> SmiteHeroList = Arrays.asList("牛魔", "苏烈", "孙策", "达摩", "刘禅");
public static void main(String args[]) {
/*
* (1)客户端知道调用者时,直接使用相应的策略
*/
CowDemonEnterArena();
/*
* (2)不知道调用者时,结合if else 或switch 使用相应的策略;
* 所以策略模式也可做分支语句的优化
*/
heroEnterArena("张良");
heroEnterArena("白起");
heroEnterArena("达摩");
heroEnterArena("西施");
}
/**
* 牛魔进场
*/
private static void CowDemonEnterArena() {
// 牛魔二技能击飞效果
HeroContext heroContext = new HeroContext();
String heroName = "牛魔";
log.info("{}闪现给到大招,二技能进场", heroName);
heroContext.setSkill(new SmiteStrategy());
heroContext.releaseSkill();
}
/**
* 英雄进场
*/
private static void heroEnterArena(String heroName) {
// 默认减速效果
HeroSkillStrategy heroSkillStrategy = new DecelerateStrategy();
if (SuppressHeroList.contains(heroName)) {
heroSkillStrategy = new SuppressStrategy();
} else if (TauntHeroList.contains(heroName)) {
heroSkillStrategy = new TauntStrategy();
} else if (SmiteHeroList.contains(heroName)) {
heroSkillStrategy = new SmiteStrategy();
} else {
log.warn("新英雄 {} 体验服公测中,请维护技能控制策略。", heroName);
}
log.info("{}进场", heroName);
HeroContext heroContext = new HeroContext();
heroContext.setSkill(heroSkillStrategy);
heroContext.releaseSkill();
}
}
测试结果如下:
5.4 完善环境类,减少客户端代码
我们可以在环境类提供按类型适配具体实现策略的方法,把客户端的分支判断交给环境类维护,客户端可以直接传已知的类型即可,具体策略的选择交个环境类处理。使得客户端代码更简洁,代码复用性更好,客户端使用具体策略的场景比较多的情况下,这个情况更明显。
- 环境类 HeroSkillContext.java
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
/**
* @className: HeroSkillContext
* @description: 策略使用者环境
* @author: niaonao
* @date: 2019/9/26
**/
@Slf4j
public class HeroSkillContext {
/** 技能策略 */
private HeroSkillStrategy heroSkillStrategy;
/** 客户端设置具体策略 */
public void setSkill(HeroSkillStrategy heroSkillStrategy) {
this.heroSkillStrategy = heroSkillStrategy;
};
private static List<String> SuppressHeroList = Arrays.asList("东皇太一", "张良");
private static List<String> TauntHeroList = Arrays.asList("白起", "司马懿", "花木兰");
private static List<String> SmiteHeroList = Arrays.asList("牛魔", "苏烈", "孙策", "达摩", "刘禅");
/** 根据类型(此处为名称)设置合适的策略 */
public void setSkill(String heroName) {
if (SuppressHeroList.contains(heroName)) {
this.heroSkillStrategy = new SuppressStrategy();
} else if (TauntHeroList.contains(heroName)) {
this.heroSkillStrategy = new TauntStrategy();
} else if (SmiteHeroList.contains(heroName)) {
this.heroSkillStrategy = new SmiteStrategy();
} else {
this.heroSkillStrategy = new DecelerateStrategy();
log.warn("新英雄 {} 体验服公测中,请维护技能控制策略。", heroName);
}
}
/**
* 释放技能
*/
public void releaseSkill() {
heroSkillStrategy.releaseSkill();
}
}
- 模拟客户端程序 HeroSkillContextTests.java
import lombok.extern.slf4j.Slf4j;
/**
* @className: HeroSkillTests
* @description: 环境类提供按类型选择具体策略的方法,减少客户端频繁操作
* @author: niaonao
* @date: 2019/9/26
**/
@Slf4j
public class HeroSkillContextTests {
public static void main(String args[]) {
/*
* (1)客户端知道调用者时,直接使用相应的策略
*/
CowDemonEnterArena();
/*
* (2)不知道调用者时,结合if else 或switch 使用相应的策略;
* 所以策略模式也可做分支语句的优化
*/
heroEnterArena("张良");
heroEnterArena("白起");
heroEnterArena("达摩");
heroEnterArena("西施");
}
/**
* 牛魔进场
*/
private static void CowDemonEnterArena() {
// 牛魔二技能击飞效果
HeroSkillContext heroContext = new HeroSkillContext();
String heroName = "牛魔";
log.info("{}闪现给到大招,二技能进场", heroName);
heroContext.setSkill(new SmiteStrategy());
heroContext.releaseSkill();
}
/**
* 英雄进场
*/
private static void heroEnterArena(String heroName) {
// 默认减速效果
log.info("{}进场", heroName);
HeroSkillContext heroContext = new HeroSkillContext();
heroContext.setSkill(heroName);
heroContext.releaseSkill();
}
}
The End, Thanks