设计模式

第 10 章 Strategy 模式 -- 整体地替换算法

2018-09-07  本文已影响4人  oO反骨仔Oo
image.png

Strategy 模式

能够整体地替换算法,能然我们轻松地以不同地算法去解决同一个问题,这种模式就是 Strategy 模式。

Show me the codes

image.png
using 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.png

Strategy:策略

负责定义实现策略所必需地接口。对应示例地 Strategy 接口。

ConcreteStrategy:具体的策略

负责实现 Strategy 角色的接口。对应示例的 WinningStrategy 类和 ProbStrategy 类。

Context:上下文

负责使用 Strategy 角色,使用对应的 ConcreteStrategy 角色去实现需求。对应示例的 Player 类。

相关模式

Flyweight 模式

Abstracct Factory 模式

State 模式

两种模式的目的不同。
Strategy 模式中强调的是算法的替换;State 模式中,强调的是状态变化的替换。

上一篇下一篇

猜你喜欢

热点阅读