设计模式 - 策略模式理解及示例

策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

  • 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

  • 主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

  • 关键代码:实现同一个接口。

  • 优点:
    1、算法可以自由切换。
    2、避免使用多重条件判断。
    3、扩展性良好。

  • 缺点:
    1、策略类会增多。
    2、所有策略类都需要对外暴露。

  • 使用场景
    1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
    2、一个系统需要动态地在几种算法中选择一种。
    3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

示例1 - 七夕

情人节已到,男孩子需要为老婆(女朋友)准备礼物。

思来想去,给我老婆准备一束玫瑰花

/**
 * 玫瑰花
 */
class Rose
{
    //外观
    public string $appearance = "美丽";

    //寓意
    public string $moral = "爱情";
}

能过这个节日只有我们人类

/**
 * 人类
 */
interface PersonalInterface
{
    public function getName();
    public function getAge();
}

/**
 * 人类实体
 * */
class Personal implements PersonalInterface
{
    public string $name;

    public string $age;

    public function __construct(string $name,int $age)
    {
        $this->setName($name);
        $this->setAge($age);
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getAge(): string
    {
        return $this->age;
    }

    /**
     * @param string $age
     */
    public function setAge(string $age): void
    {
        $this->age = $age;
    }
}

这个美丽的节日肯定是我和老婆一起过

/**
 * 男人
 */
class ManPersonal extends Personal
{

    //搞n朵玫瑰花
    public function createMissile(int $num) : array
    {
        $arr = [];

        for($i=0;$i<$num;$i++)
            array_push($arr,new Rose());

        return $arr;
    }
}

/**
 * 女人
 */
class WomanPersonal extends Personal
{
    public function revMissile(array $roses) : string
    {
        //情景1 - 多个鲜花当中混了一束假花
        foreach($roses as $rose)
        {
            if(!($rose instanceof Rose))
                return "渣男,送花还要送假花";
        }

        //鲜花总数量
        $sumRose = count($roses);

        //女生心仪数量集合
        $womanFavorite = [
            666,99,88,999
        ];

        //情景2 - 鲜花数量不够
        if($sumRose < 10)
            return "渣男,就这么几朵花就想打动我";

        //情景3 - 鲜花数量在 10-30朵内
        if($sumRose > 10 && $sumRose<30)
            return "流氓,勉强过关";

        //情景3 - 鲜花数量在某个区间值
        if($sumRose > 30 && !in_array($sumRose,$womanFavorite))
            return "宝宝肯定很爱我";

        //情景4 - 真爱
        if(in_array($sumRose,$womanFavorite))
            return "这就我的真命天子吗?";
        
        return "渣男";
    }
}

美丽的节日有很多

/**
 * 节日
 */
interface FestivalInterface
{

}

/**
 * 情人节 - 策略模式实现
 */
class ValentineDay implements FestivalInterface
{
    public array $personals = [];

    public function __construct(PersonalInterface ...$args)
    {
        if(!empty($args))
            array_push($this->personals,...$args);
    }
	
    public function __call(string $methodName,array $params)
    {
        if(!empty($this->personals))
        {
            foreach($this->personals as $personal)
            {
                if(method_exists($personal,$methodName))
                {
                    return $personal->{$methodName}(...$params);
                }
            }
        }

        throw new \Exception('not exec',101);
    }
}

开始行动,看看我给老婆送花会有什么结果


//男人
$man = new ManPersonal('谭勇',27);

//女人
$woman = new WomanPersonal('王玉梅',26);

//情人节到了
$festival = new ValentineDay($man,$woman);


//准备1朵玫瑰花
$missiles = $festival->createMissile(1);

//把玫瑰花送给老婆
$result = $festival->revMissile($missiles);

var_dump($result);//渣男,就这么几朵花就想打动我

//准备19朵玫瑰花
$missiles = $festival->createMissile(19);

//把玫瑰花送给老婆
$result = $festival->revMissile($missiles);

var_dump($result);//流氓,勉强过关

//准备56朵玫瑰花
$missiles = $festival->createMissile(56);

//把玫瑰花送给老婆
$result = $festival->revMissile($missiles);

var_dump($result);//宝宝肯定很爱我

//准备999朵玫瑰花
$missiles = $festival->createMissile(999);

//把玫瑰花送给老婆
$result = $festival->revMissile($missiles);

var_dump($result);//这就我的真命天子吗?

男孩子要时常关心和保护女孩子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值