设计模式之策略模式

本文详细介绍了策略模式在模拟鸭子应用中的应用,通过实例展示了如何从简单的鸭子模型逐步改进到采用策略模式,以解决代码重复、运行时行为不易改变等问题。策略模式遵循面向接口编程、多用组合少用继承等设计原则,使得鸭子的行为可以通过不同的策略类灵活组合,实现了代码的可扩展性和重用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

策略模式

目录

策略模式

一、从简单的模拟鸭子应用开始

二、改进版的鸭子应用

三、采用策略模式改进后的鸭子应用

3.1 策略模式中包含的设计原则

3.2 具体的方法

四、总结


一、从简单的模拟鸭子应用开始

Joe上班的公司做了一套模拟鸭子的游戏:SimUDuck。游戏中的各种鸭子一边游泳戏水,一边呱呱叫。此系统内部设计使用了标准的OO技术,设计了一个鸭子超累,并且让各种鸭子继承此超类。

              

public abstract class Duck {     //抽象类

	public Duck() {
	}

	public void Quack() {
		System.out.println("~~gaga~~");
	}

	public abstract void display();    //抽象方法,每个子类都必须实现该方法

	public void swim() {
		System.out.println("~~im swim~~");
	}
	
	
	public void Fly() {    //添加一个fly()方法
			System.out.println("~~im fly~~");
		}
	
	
public class RedHeadDuck extends Duck {

	@Override
	public void display() {
		System.out.println("**RedHead**");
	}

此时项目中需要添加新的功能,比说要程序中需要有会飞的鸭子,此时Joe在Duck类上添加了fly方法,这种方法有个弊端,所有的子类都会包含有fly方法,并非所有的duck类的子类都会飞。

Joe想到一个方法:用覆盖的方式把不会飞的子类中fly方法覆盖掉


public class GreenHeadDuck extends Duck {
    //不会飞的鸭子

	@Override
	public void display() {
		System.out.println("**GreenHead**");
	}

	public void Fly() {    //覆盖
		System.out.println("~~no fly~~");
	}
	
	
	
}

用继承的方式来提供Duck的行为,会导致以下缺点:

1.代码会在多个子类中重复

2.运行时的行为不容易改变

3.无法得知所有鸭子的全部行为,并且鸭子不能够同时飞又叫

4.改变Duck类代码,会影响其他鸭子一起发生改变

二、改进版的鸭子应用

Joe把fly方法抽取出来,放进一个flyable接口中,这样一来,只有会飞的鸭子才实现此接口。同样的他也可以设计一个Quackable接口,并不是所有的鸭子都会叫。

这样子的方法同样也产生了一个问题,就是代码不能重用,每个子类都必须实现接口,如果有48个会飞的鸭子,那么就要实现48个飞的接口。

三、采用策略模式改进后的鸭子应用

3.1 策略模式中包含的设计原则

a.找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变的代码混在一起。把会变化的部分抽取出来并且封装起来,一边以后可以轻易地扩充此部分,而不影响不需要变化的部分。

b.针对接口编程,而不是针对实现编程

c.多用组合,少用继承

3.2 具体的方法

步骤一:为了分开【变化与不变化】的部分,建立了两组类,分别是fly相关,quack相关,每一组类将实现各自的动作。

步骤二:如何设计鸭子的行为(采用设计原则b)

利用接口代表每个行为,比如:FlyBehavior与QuackBehavior,而行为的每个实现都必须实现这些接口之一。所以鸭子不会负责实现Flying和Quacking接口,而是其他类专门实现FlyBeahavir和QuackBehavior接口,这就是行为类。由行为类实现行为接口而不是通过duck类实现行为接口。

这种做法不同于以往的做法,以往的做法是:行为继承Duck超类的具体实现而来,或者是继承某个接口并由子类自行实现。这些方法都依赖于实现。

                      

问题:为什么不把FlyBehavior设计成抽象超类,而是接口

  针对接口编程的真正意思是针对超类型编程,针对接口编程关键在于多态。利用多态,程序可以针对超类型编程,执行的时候会根据实际状况得到真正的行为,不会被绑死在超类型的行为上。超类型通常是一个抽象类或者一个接口。例子如下:

                                        

                                  

步骤三:实现鸭子行为

这样设计的好处:可以让飞行和呱呱叫的动作被其他对象复用,这些行为已经和鸭子类无关了。如果我们需要新增一些行为,不会影响到已有的行为类,而不会影响到使用飞行行为的鸭子类。

步骤四:整个鸭子的行为

 

具体代码如下:

Duck类:

package com.java.hexter.stimulateduck.duck;

import com.java.hexter.stimulateduck.flybehavior.FlyBehavior;
import com.java.hexter.stimulateduck.quackbehavior.QuackBehavior;

public abstract class Duck {

	FlyBehavior mFlyBehavior;
	QuackBehavior mQuackBehavior;

	public Duck() {

	}

	public void Fly() {
		mFlyBehavior.fly();
	}

	public void Quack() {
		mQuackBehavior.quack();
	}

	public abstract void display();

	public void SetQuackBehavoir(QuackBehavior qb) {    //动态的设定行为
		mQuackBehavior = qb;
	}

	public void SetFlyBehavoir(FlyBehavior fb) {         //动态的设定行为
		mFlyBehavior = fb;
	}

	public void swim() {
		System.out.println("~~im swim~~");
	}
}

GreenHeadDuck类

package com.java.hexter.stimulateduck.duck;

import com.java.hexter.stimulateduck.flybehavior.GoodFlyBehavior;
import com.java.hexter.stimulateduck.quackbehavior.GaGaQuackBehavior;

public class GreenHeadDuck extends Duck {

	public GreenHeadDuck() {
		mFlyBehavior = new GoodFlyBehavior();
		mQuackBehavior = new GaGaQuackBehavior();
	}

	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("**GreenHead**");
	}

}

RedHeadDuck类

package com.java.hexter.stimulateduck.duck;

import com.java.hexter.stimulateduck.flybehavior.BadFlyBehavior;

import com.java.hexter.stimulateduck.quackbehavior.GeGeQuackBehavior;

public class RedHeadDuck extends Duck {

	public RedHeadDuck() {
		mFlyBehavior = new BadFlyBehavior();
		mQuackBehavior = new GeGeQuackBehavior();
	}

	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("**RedHead**");
	}

}

 

飞行行为类:

package com.java.hexter.stimulateduck.flybehavior;

public interface FlyBehavior {
	void fly();
}
package com.java.hexter.stimulateduck.flybehavior;

public class BadFlyBehavior implements FlyBehavior
{
	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("--BadFly--");
	}
}
package com.java.hexter.stimulateduck.flybehavior;

public class  GoodFlyBehavior implements FlyBehavior
{
	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("--GoodFly--");
	}	
}
package com.java.hexter.stimulateduck.flybehavior;

public class NoFlyBehavior implements FlyBehavior
{
	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("--NoFly--");
	}
}

 

 

 

 

呱呱叫行为类: 

package com.java.hexter.stimulateduck.quackbehavior;

public	interface QuackBehavior {
	void quack();
};
package com.java.hexter.stimulateduck.quackbehavior;

public	class NoQuackBehavior implements QuackBehavior
{
	@Override
	public void quack() {
		// TODO Auto-generated method stub
		System.out.println("__NoQuack__");
	}
	
}
package com.java.hexter.stimulateduck.quackbehavior;

public	class GeGeQuackBehavior implements QuackBehavior
{
	@Override
	public void quack() {
		// TODO Auto-generated method stub
		System.out.println("__GeGe__");
	}
	
}
package com.java.hexter.stimulateduck.quackbehavior;

public	class GaGaQuackBehavior implements QuackBehavior
{
	@Override
	public void quack() {
		// TODO Auto-generated method stub
		System.out.println("__GaGa__");
	}
	
}

测试代码:

package com.java.hexter.stimulateduck;

import com.java.hexter.stimulateduck.duck.Duck;
import com.java.hexter.stimulateduck.duck.GreenHeadDuck;
import com.java.hexter.stimulateduck.duck.RedHeadDuck;
import com.java.hexter.stimulateduck.flybehavior.NoFlyBehavior;
import com.java.hexter.stimulateduck.quackbehavior.NoQuackBehavior;


public class StimulateDuck {

	public static void main(String[] args) {

		Duck mGreenHeadDuck = new GreenHeadDuck();
		Duck mRedHeadDuck = new RedHeadDuck();

		mGreenHeadDuck.display();
		mGreenHeadDuck.Fly();
		mGreenHeadDuck.Quack();
		mGreenHeadDuck.swim();

		mRedHeadDuck.display();
		mRedHeadDuck.Fly();
		mRedHeadDuck.Quack();
		mRedHeadDuck.swim();
		mRedHeadDuck.display();
		mRedHeadDuck.SetFlyBehavoir(new NoFlyBehavior());    //动态修改行为
		mRedHeadDuck.Fly();
		mRedHeadDuck.SetQuackBehavoir(new NoQuackBehavior());    //动态修改行为
		mRedHeadDuck.Quack();
	}

}

 

四、总结

本案例采用的是策略模式,该模式覆盖三个设计原则,分别是面向接口编程多用组合少用继承将程序中可变与不可变的部分分开,其中多用组合少用继承是一种十分重要的技巧,案例中每一鸭子都有一个FlyBehavior和一个QuackBehavior,让鸭子将飞行和呱呱叫委托给他们代为处理。鸭子的行为不是继承而来的,而是采用适当的行为对象组合而来。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值