第 10 章 Strategy 模式 -- 整体地替换算法
2018-09-07 本文已影响4人
oO反骨仔Oo
image.png
Strategy 模式
能够整体地替换算法,能然我们轻松地以不同地算法去解决同一个问题,这种模式就是 Strategy 模式。
Show me the codes
image.pngusing System.Collections.Generic;
namespace StrategyPattern
{
/// <summary>
/// 手势
/// </summary>
internal class Hand
{
public static int Guu = 0;
public static int Cho = 1;
public static int Paa = 2;
public static List<Hand> Hands = new List<Hand>
{
new Hand(Guu),
new Hand(Cho),
new Hand(Paa)
};
private static readonly string[] Names = {"石头", "剪刀", "布"};
private readonly int _handValue;
private Hand(int handValue)
{
_handValue = handValue;
}
/// <summary>
/// 获取手势
/// </summary>
/// <param name="handValue"></param>
/// <returns></returns>
public static Hand GetHand(int handValue)
{
return Hands[handValue];
}
/// <summary>
/// 是否强于
/// </summary>
/// <param name="hand"></param>
/// <returns></returns>
public bool IsStrongerThan(Hand hand)
{
return Fight(hand) == 1;
}
/// <summary>
/// 是否弱于
/// </summary>
/// <param name="hand"></param>
/// <returns></returns>
public bool IsWeakerThan(Hand hand)
{
return Fight(hand) == -1;
}
public override string ToString()
{
return Names[_handValue];
}
/// <summary>
/// 猜拳
/// </summary>
/// <param name="hand"></param>
/// <returns></returns>
private int Fight(Hand hand)
{
return this == hand ? 0 : ((_handValue + 1) % 3 == hand._handValue ? 1 : -1);
}
}
}
namespace StrategyPattern
{
/// <summary>
/// 策略
/// </summary>
internal interface IStrategy
{
/// <summary>
/// 下一个手势
/// </summary>
/// <returns></returns>
Hand NextHand();
/// <summary>
/// 学习
/// </summary>
/// <param name="win"></param>
void Study(bool win);
}
}
using System;
namespace StrategyPattern
{
/// <summary>
/// 胜者策略
/// </summary>
internal class WinningStrategy : IStrategy
{
private readonly Random _random;
private Hand _prevHand;
private bool _won;
public WinningStrategy()
{
_random = new Random();
}
public Hand NextHand()
{
if (!_won)
{
_prevHand = Hand.GetHand(_random.Next(3));
return _prevHand;
}
return _prevHand;
}
public void Study(bool win)
{
_won = win;
}
}
}
using System;
namespace StrategyPattern
{
/// <summary>
/// 概率策略
/// </summary>
internal class ProbStrategy : IStrategy
{
private readonly Random _random;
private Hand _prevHand;
private bool _won;
public ProbStrategy()
{
_random = new Random();
}
public Hand NextHand()
{
if (_won || _prevHand == null)
{
_prevHand = Hand.GetHand(_random.Next(3));
return _prevHand;
}
return _prevHand;
}
public void Study(bool win)
{
_won = win;
}
}
}
namespace StrategyPattern
{
/// <summary>
/// 选手
/// </summary>
internal class Player
{
private int _gameCount;
private int _loseCount;
private readonly string _name;
private readonly IStrategy _strategy;
private int _winCount;
public Player(string name, IStrategy strategy)
{
_name = name;
_strategy = strategy;
}
/// <summary>
/// 下一次手势
/// </summary>
/// <returns></returns>
public Hand NextHand()
{
return _strategy.NextHand();
}
/// <summary>
/// 胜
/// </summary>
public void Win()
{
_strategy.Study(true);
_winCount++;
_gameCount++;
}
/// <summary>
/// 负
/// </summary>
public void Lose()
{
_strategy.Study(false);
_loseCount++;
_gameCount++;
}
/// <summary>
/// 平
/// </summary>
public void Even()
{
_gameCount++;
}
public override string ToString()
{
return $"【{_name}: {_gameCount}games, {_winCount}win, {_loseCount}lose】";
}
}
}
using System;
namespace StrategyPattern
{
internal class Program
{
private static void Main(string[] args)
{
var p1 = new Player("P1", new WinningStrategy());
var p2 = new Player("P2", new ProbStrategy());
for (var i = 0; i < 1000; i++)
{
var nextHand1 = p1.NextHand();
var nextHand2 = p2.NextHand();
if (nextHand1.IsStrongerThan(nextHand2))
{
Console.WriteLine($"Winner: {p1}");
p1.Win();
p2.Lose();
}
else if (nextHand2.IsStrongerThan(nextHand1))
{
Console.WriteLine($"Winner: {p2}");
p1.Lose();
p2.Win();
}
else
{
Console.WriteLine("Even...");
p1.Even();
p2.Even();
}
}
Console.Read();
}
}
}
image.png
角色梳理
image.pngStrategy:策略
负责定义实现策略所必需地接口。对应示例地 Strategy 接口。
ConcreteStrategy:具体的策略
负责实现 Strategy 角色的接口。对应示例的 WinningStrategy 类和 ProbStrategy 类。
Context:上下文
负责使用 Strategy 角色,使用对应的 ConcreteStrategy 角色去实现需求。对应示例的 Player 类。
相关模式
Flyweight 模式
Abstracct Factory 模式
State 模式
两种模式的目的不同。
Strategy 模式中强调的是算法的替换;State 模式中,强调的是状态变化的替换。