设计模式学习:策略模式分析

1.举例分析

问题:
要想实现一套模拟鸭子的游戏,鸭子种类很多,有绿头鸭、红头鸭、橡皮鸭和诱饵鸭。鸭子动作很多,动作包括叫法和飞行,且不同种类鸭子叫法不同,飞行行为不同。
难点:
鸭子种类和鸭子动作都会随着业务的改变而发生扩展或减少。
怎么办?

2.定义:策略模式

策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

3.设计原则

3.1 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

解释:
1.如果每次新的需求一来,都会使某方面的代码发生变化,那么你就可以确定,这部分代码需要被抽出来,和其他稳定的代码有所区分。
2.可以使得系统中的某部分改变不会影响其他部分。

3.2 针对接口编程,而不是针对实现编程。

解释:
1.利用接口代表每个行为,而行为的每个实现都将实现其中的一个接口。
2.可以通过增加和减少行为类,来增加和减少操作,而不是修改代码。
3.使用接口“实现”,不会被绑定在特定的对象中,也就是“针对超类型编程”

3.3 多用组合,少用继承。

解释:
1.使用组合建立系统具有很大的弹性,不仅可以将算法族(行为库)封装成类,更可以在“运行时改变行为”,只要组合的行为对象符合正确的接口标准。
2.“组合”用在很多设计模式中。

4.解决办法:策略模式图片解释

在这里插入图片描述

4.1 定义FlyBehavior行为接口

//所有飞行行为必须实现的接口
public interface FlyBehavior{
	public void fly();
}

实现接口,也就是写很多飞行行为的算法。
1.行为一:FlyNoWay行为类(新建)

public class FlyNoWay implements FlyBehavior {
	public void fly() {
		//这是飞行行为的实现,给“不会”飞的鸭子使用,包括橡皮鸭和诱饵鸭
		System.out.println("I can't fly!");
	}
}

2.行为二: FlyRocketPowered行为类(新建)

//建立一个利用火箭动力飞行的行为
public class FlyRocketPowered implements FlyBehavior{
	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("I'm flying with a rocket!");
	}
}

3.行为三: FlyWithWings行为类(新建)

public class FlyWithWings implements FlyBehavior {
	public void fly() {
		//这是飞行行为的实现,给“真会”飞的鸭子使用
		System.out.println("I'm flying!!");
	}
}

备注:要是在实际业务中,这类的行为不够用,还可以动态地扩展和缩减。是不是很有弹性?

4.2 定义QuackBehavior行为接口

public interface QuackBehavior {
	public void quack();
}

实现接口,也就是写很多呱呱叫行为的算法。
1.行为一:MuteQuack行为类(新建)

public class MuteQuack implements QuackBehavior{
	public void quack() {
		System.out.println("<<Silence!>>");
	}
}

2.行为二:Quack行为类(新建)

public class Quack implements QuackBehavior{
	public void quack() {
		System.out.println("Quack!");
	}
}

2.行为三:Squeak行为类(新建)

public class Squeak implements QuackBehavior{
	public void quack() {
		System.out.println("Squeak!");
	}
}

备注:要是在实际业务中,这类的行为不够用,还可以动态地扩展和缩减。是不是很有弹性?

4.3 定义Duck超类

定义Duck超类,如果需要新增加一种类型的鸭子,就来继承这个Duck超类。

import FlyBehavior.FlyBehavior;
import QuackBehavior.QuackBehavior;

public abstract class Duck {
	//行为变量被申明为“行为接口”类型,所有鸭子子类(在同一个package中)都继承它们。
	//每只鸭子都会引用实现FlyBehavior接口的对象
	FlyBehavior flyBehavior;
	//每只鸭子都会引用实现QuackBehavior接口的对象
	QuackBehavior quackBehavior;
	
	public Duck() {
	};
	
	//抽象方法,
	public abstract void display();
	
	public void performFly() {
		//鸭子对象不亲自处理呱呱叫行为,而是委托给flyBehavior引用的对象
		flyBehavior.fly();
	}
	
	public void performQuack() {
		//鸭子对象不亲自处理呱呱叫行为,而是委托给quackBehavior引用的对象
		quackBehavior.quack();
	}
	
	public void swim() {
		System.out.println("All ducks float, even decoys!");
	}
	
	//注意下面方法的添加,很经典
	//从此以后,我们可以随时调用这两个方法改变鸭子的行为
	public void setFlyBehavior(FlyBehavior fb) {
		flyBehavior = fb;
	}
	
	public void setQuackBehavior(QuackBehavior qb) {
		quackBehavior = qb;
	}
	
}

4.4 加入业务来了,增加一些种类的鸭子

这时候突然来了一个鸭子(MallardDuck),那么就继承Duck超类,建立一种类型的鸭子出来:

//绿头鸭
public class MallardDuck extends Duck {
	//别忘了,因为MallardDuck继承Duck类,所以具有flyBehavior与quackBehavior实例变量
	/*
	 *FlyBehavior flyBehavior;
	 *QuackBehavior quackBehavior;
	 */
	public MallardDuck() {
		//绿头鸭使用Quack类处理呱呱叫,叫的职责被委托给Quack对象。
		quackBehavior = new Quack();
		//使用FlyWithWings作为其FlyBehavior类型
		flyBehavior = new FlyWithWings();
	}

	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("I'm a real Mallard duck!");

	}

}

这时候又来了一个鸭子(ModelDuck),那么就继续继承Duck超类,建立一种新类型的鸭子出来:

import FlyBehavior.FlyNoWay;
import QuackBehavior.Quack;

public class ModelDuck extends Duck{
	//别忘了,因为ModelDuck继承Duck类,所以具有flyBehavior与quackBehavior实例变量
	/*
	 *FlyBehavior flyBehavior;
	 *QuackBehavior quackBehavior;
	 */
	public ModelDuck() {
		//一开始,模型鸭是不会飞的
		flyBehavior = new FlyNoWay();
		quackBehavior = new Quack();
	}

	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("I'm a model duck!");
	}

}

要是新业务来了,我们又可以增加新的子类鸭子啦,不用更改原来的代码。这样就容易扩展,代码很有弹性

5.测试一下

import FlyBehavior.FlyRocketPowered;

public class MiniDuckSimulator {
	public static void main(String[] args) {
		//这会调用MallardDuck继承来的performQuack()方法,进而委托给该对象的QuackBehavior对象处理
		//也就是说:调用继承来的quackBehavoir引用对象的quack()方法。
		Duck mallard = new MallardDuck();
		mallard.performQuack();
		mallard.performFly();
		mallard.display();
		mallard.swim();
		
		System.out.println("--------------------------------");
		Duck model = new ModelDuck();
		model.performFly();
		model.setFlyBehavior(new FlyRocketPowered());
		model.performFly();
	}

}

输出:

Quack!
I'm flying!!
I'm a real Mallard duck!
All ducks float, even decoys!
--------------------------------
I can't fly!
I'm flying with a rocket!

结合图片解释看,更容易理解噢!

要是觉得上面的代码难敲,这里有下载方式(运行环境Eclipse,语言:Java):
提取码:hoke

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值