设计模式--策略模式

Posted dxj1016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式--策略模式相关的知识,希望对你有一定的参考价值。

设计模式分为三种类型,共23种

  1. 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式。
  2. 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
  3. 行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)。

创建型模式主要用于创建对象
结构型模式主要用于处理类或对象的组合
行为型模式主要用于描述类或对象如何交互和怎样分配职责

1、基本介绍

  1. 策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以
    互相替换,此模式让算法的变化独立于使用算法的客户。
  2. 这算法体现了几个设计原则:
    1. 第一、把变化的代码从不变的代码中分离出来;
    2. 第二、针对接口编程而不是具体类(定义了策略接口);
    3. 第三、多用组合/聚合,少用继承(客户通过组合方式使用策略)。

2、例子分析

  1. 其它鸭子,都继承了Duck类,所以fly让所有子类都会飞了,这是不正确的
  2. 上面说的1 的问题,其实是继承带来的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。会有溢出效
  3. 为了改进1问题,我们可以通过覆盖fly 方法来解决 => 覆盖解决
  4. 问题又来了,如果我们有一个玩具鸭子ToyDuck, 这样就需要ToyDuck去覆盖Duck
    的所有实现的方法 => 解决思路 策略模式 (strategy pattern)

3、例子代码

思路分析
策略模式: 分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为的变化独立于算法的使用者

超类:

package designpattern.strategy.improve1;

public abstract class Duck {
//为行为接口类型声明两个引用变量
	FlyBehavior flyBehavior;

	QuackBehavior quackBehavior;
	public Duck() {

	}

	public abstract void display();//显示鸭子信息

	public void performFly() {
		flyBehavior.fly();//委托给行为类
	}

	public void performQuack() {
		quackBehavior.quack();//委托给行为类
	}

	public void swim() {
		System.out.println("鸭子会游泳~~");
	}


	public void setFlyBehavior(FlyBehavior flyBehavior) {
		this.flyBehavior = flyBehavior;
	}


	public void setQuackBehavior(QuackBehavior quackBehavior) {
		this.quackBehavior = quackBehavior;
	}

}

会变动的行为接口–飞行行为

package designpattern.strategy.improve1;
//所有飞行行为类必须实现的接口
public interface FlyBehavior {
	
	void fly(); // 子类具体实现
}

两个类实现飞行接口

package designpattern.strategy.improve1;
//这是飞行行为的实现,给不会飞的鸭子用
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("这是不会飞的鸭子");
    }
}

package designpattern.strategy.improve1;
//这是飞行行为的实现,给会飞的鸭子用
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("这是真的会飞的鸭子");
    }
}

会变动的行为接口–叫声行为

package designpattern.strategy.improve1;
//所有叫的行为类必须实现的接口
public interface QuackBehavior {
    public void quack();
}

三个类实现叫声行为

package designpattern.strategy.improve1;

public class QuackNoWay implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("这是不会叫的鸭子");
    }
}

package designpattern.strategy.improve1;

public class QuackWithGuaGua implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("呱呱叫");
    }
}

package designpattern.strategy.improve1;

public class QuackWithZhiZhi implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("吱吱叫");
    }
}

实现鸭子的类

package designpattern.strategy.improve1;

public class MallardDuck extends Duck {
    public MallardDuck() {
        quackBehavior = new QuackWithGuaGua();
        flyBehavior = new FlyWithWings();
    }
    
    @Override
    public void display() {
        System.out.println("display");
    }
}

测试类

package designpattern.strategy.improve1;

public class Client {
    public static void main(String[] args) {
        Duck duck = new MallardDuck();
        duck.performFly();
        duck.performQuack();
    }
}
/*
这是真的会飞的鸭子
呱呱叫
*/

在duck中的两个set方法没用上,可以调用这两个set方法改变鸭子的行为
再创建一个模型鸭子来继承超类,这个模型鸭子不会飞也不会叫:

package designpattern.strategy.improve1;

public class ModelDuck extends Duck {
    public ModelDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new QuackNoWay();
    }

    @Override
    public void display() {
        System.out.println("这是一个不会飞不会叫的鸭子");
    }
}

再写一个会利用火箭来飞的飞行行为

package designpattern.strategy.improve1;

public class FlyRocket implements FlyBehavior {

    @Override
    public void fly() {
        System.out.println("这个是利用火箭动力的飞行行为");
    }
}

重新写测试类

package designpattern.strategy.improve1;

public class Client {
    public static void main(String[] args) {
        Duck duck = new MallardDuck();
        duck.performFly();
        duck.performQuack();
        Duck duck1 = new ModelDuck();
        duck1.performFly();//改变前是不会飞的
        duck1.setFlyBehavior(new FlyRocket());//在运行时改变了飞行行为
        duck1.performFly();//改变后为火箭飞行

    }
}
/*
这是真的会飞的鸭子
呱呱叫
这是不会飞的鸭子
这个是利用火箭动力的飞行行为
*/

在运行时想要修改鸭子的行为,只需要调用鸭子的setter方法即可;如要添加新的行为,只需要加个类然后实现飞行行为或者叫声行为,然后可以在客户端调用setter方法动态改变行为

以上是关于设计模式--策略模式的主要内容,如果未能解决你的问题,请参考以下文章

Redis实现分布式锁(设计模式应用实战)

设计模式策略模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式