24种设计模式之策略模式

24种设计模式之策略模式

设计模式入门:

在这里插入图片描述

问题提出

a. 开发一个鸭子应用
b. 基于oo(面向对象: 封装 继承 多态 )
c. 满足 新的需求新增 而且效率 很高 时间复杂度为O(n)
d. 用OO原则解决新需求的不足
e. 用策略模式来新需求解决
f. 总结策略模式定义

一、开发一个鸭子应用

1、从项目"模拟鸭子游戏"开始
2、从OO的角度设计这个项目,鸭子超类,扩展超类:
// 超类 鸭子🦆



public abstract class Duck{
    public Duck() {
    }
    /**
     * default methods
     * define behavior
     *默认的行为方式需要子类实现 
     */
    public abstract void deploy();
}

子类例如有 绿🦆 红🦆

public class GreenDuke extends Duke{
    @Override
    public void deploy() {
        //实现基本属性
        System.out.println("--gaga-- 叫");
    }
}
// 红鸭子-----------------------
public class RedDuke extends Duke{
    @Override
    public void deploy() {
        //实现基本属性
        System.out.println("--gaga-- 叫");
    }
}

3、如果新增需求 ,鸭子可以飞

OO思维里的继承方式解决方案是:
// 超类 鸭子🦆

public abstract class Duck{
    public Duck() {
    }
    /**
     * default methods
     * define behavior
     *默认的行为方式需要子类实现 
     */
    public abstract void deploy();
    //该鸭子可以飞 只要继承该duke 就有飞的属性  
    //子类不用实现 
    // 这个Fly让所有子类都会飞了,这是不科学的。
    // 继承的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。影响会有溢出效应
    public void fly(){
        System.out.println("飞向天空");
    }
    
}

4、难度增加
如果在更改一下 在原来飞的基础上加上 :某些鸭子不能飞 ;有些鸭子可以飞
如果还是用oo原则实现
1、继续尝试用OO原理来解决,覆盖:


public class RedDuck extends Duck {
...public void Fly() {
        System.out.println("~~no fly~~");
    }   
}

又有新需求,石头鸭子,填坑:
public class StoneDuck extends Duck {
… };
超类挖的一个坑,每个子类都要来填,增加工作量,复杂度O(N^2)。不是好的设计方式
所以 以上的方式 就不能满足了 ,需要一种新的设计方式

二 、 策略模式

新的设计方式应该保证 应对项目的扩展性,降低复杂度:
1)分析项目变化与不变部分,提取变化部分,抽象成接口+实现;
2)鸭子哪些功能是会根据新需求变化的?飞行。。。。

ublic interface Fly {
    void dukeFly();
}
// 3)好处:新增行为简单,行为类更好的复用,组合更方便。既有继承带来的复用好处,没有挖坑
// 实现类 例如有的飞的好 、有的飞的不好 
public class BadFlyImpl implements Fly {
    @Override
    public void dukeFly() {
        System.out.println("坏的飞行方式");
    }
}
// --------------------
public class GoodFlyImpl implements Fly {
    @Override
    public void dukeFly() {
        System.out.println("好的飞行方式");
    }
}

1、重新设计一下 这个游戏项目

public abstract class Duck {
    // 在超类里面将接口对象放在这,在子类里面设定行为对象
    Fly fly;
    public Duck() { }
    
    // 把之前飞写的方式改成 fly 接口对象的方法 由不同的实现类实现不同的算法逻辑
    public void Fly() {
        fly.dukeFly();
    }
    public abstract void display();
    }
}
// -- 绿鸭子 
public class GreenDuck extends Duck {
    @Override
    public void display() {
        //实现基本属性
        System.out.println("--gaga-- 叫");
    }
    // 在子类中给定他相对应的飞的属性 
    public GreenDuck() {
        fly = new GoodFlyImpl();
    }
}
// -- 红鸭子
public class RedDuck extends Duck {
    @Override
    public void display() {
        System.out.println("--gege-- 叫");
    }
    
    // 在子类中给定他相对应的飞的属性 
    public GreenDuck() {
        fly = new BadFlyImpl();
    }
    
}
// 接口类 
public interface Fly {
    void dukeFly();
}
// 3)好处:新增行为简单,行为类更好的复用,组合更方便。既有继承带来的复用好处,没有挖坑
// 实现类 例如有的飞的好 、有的飞的不好 
public class BadFlyImpl implements Fly {
    @Override
    public void dukeFly() {
        System.out.println("坏的飞行方式");
    }
}
// --------------------
public class GoodFlyImpl implements Fly {
    @Override
    public void dukeFly() {
        System.out.println("好的飞行方式");
    }
}

这样以抽象+接口的方式就能 满足以上问题 ,但是现在使用都是在构造函数里面使用不符合我们平时在代码里面写的
xxxDO xx = new xxxDO();的操作 我们可以优化一下

2、优化方案

在超类里面加上一个方法就可以自由调用了

public abstract class Duck {
    // 在超类里面将接口对象放在这,在子类里面设定行为对象
    Fly fly;
    public Duck() { }
    
    // 把之前飞写的方式改成 fly 接口对象的方法 由不同的实现类实现不同的算法逻辑
    public void Fly() {
        fly.dukeFly();
    }
    public abstract void display();
    }
// 这样我们就可以在代码里方便使用了 
    public void SetMyFly(Fly myFly){
        this.fly = myFly
    }
}

4、测试


/**
 * @Classname DukeMain
 * @Description TODO
 * @Date 2020-08-31 14:48
 * @Created by buying
 */
public class DukeMain {
    public static void main(String [] a){
        //测试策略模式的接口
        //1 . 在构造函数里面 调用
        Duck green = new GreenDuck();
        Duck red = new RedDuck();
        System.out.println("****=绿头鸭行为=****");
        green.display();
        green.fly();
        // 自由调用
        green.SetMyFly(new GoodFlyImpl());
        System.out.println("****==红头鸭行为==****");
        red.display();
        red.fly();
        //red.SetMyFly(new BadFlyImpl());  
        System.out.println();
    }
}

结果

在这里插入图片描述

总结
策略模式:
(1).分别封装行为接口 (飞 、跑 、叫等), 实现算法族(即行为接口的实现),超类里面放行为接口对象,在 子类里面设定行为对象。
(2)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到超类里面,从而避免代码重复。
(3)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
原则
分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者
举栗子:分离鸭子 能否飞行的功能以接口方式独立出来,如果有的鸭子可以飞行那就实现该行为接口
策略模式的缺点
①策略类数量增多,策略类数量增多,每一个策略都是一个类,复用的可能性很小,类数量增多。
②所有的策略类都需要对外暴露,上层模块必须知道有哪些策略,然后才能决定使用哪一个策略,这与迪米特法则是相违背的,可以使用工厂方法模式、代理模式修整这个缺陷。
(工厂| 代理)模式 后面会有所阐述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值