策略模式與簡單java例項

sunbo1591發表於2010-11-25
策略模式的定義:[color=red]定義了演算法簇,分別封裝起來,讓它們之間可以相互替換,此模式讓演算法的變化獨立於使用演算法的客戶。[/color]

首先看策略模式的定義,[color=red]演算法簇[/color]也就是一群實現了同一個介面的實現類,[color=red]讓它們之間可以相互替換[/color]的意思也就是要針對介面程式設計,而不是針對類程式設計。[color=red]此模式讓演算法的變化獨立於使用演算法的客戶[/color]是說,採用何種演算法只取決於呼叫者。

現在說說例子:
一個格鬥遊戲,角色類Fighter可以使用很多武器,不同武器攻擊力以及特殊效果不同,比如使用劍能有一定機率造成額外傷害,斧子有一定機率造成雙倍傷害。如果不使用模式的情況下實現這個遊戲的話,Fighter就應該有一些方法:attackWithSword(),attackWithAxe()。如果劍類武器又有:鐵劍、霜之哀傷,又要為這兩把劍寫兩個方法。如果有1000個武器呢?(當然實現這個的方法還有很多,尤其是笨方法很多。。。)
為了避免以上情況,我們定義一個介面:

package com.Weapon;

import com.fighter.Fighter;

public interface WeaponBehavior {
public void attackWithWeapon(Fighter fighter);
public String getName();
public void setName(String name);
}



讓所有武器去實現這個介面,所有實現了這個介面的類,都叫演算法簇。

現在,抽象類劍,實現了這個介面,這裡劍是一個種類,而不是一個具體武器,所以是抽象類:

package com.Weapon;

import java.util.Random;

import com.fighter.Fighter;

//劍類武器有一定機率造成額外的傷害
public abstract class Sword implements WeaponBehavior {
// 普通傷害
int damage;
String name;
// 特殊攻擊的傷害
int specialDamage;
// 特殊攻擊的觸發機率
int probability;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getDamage() {
return damage;
}

public void setDamage(int damage) {
this.damage = damage;
}

@Override
public void attackWithWeapon(Fighter fighter) {
normalAttack(fighter);
specialAttack(fighter);
}

protected void normalAttack(Fighter fighter) {
System.out.println("用" + this.getName() + "對" + fighter.getName()
+ "造成了" + this.getDamage() + "基本傷害。");
fighter.loseLife(this.getDamage());
}

protected void specialAttack(Fighter fighter) {
Random r = new Random();
int i = r.nextInt(100);
if (i < this.probability) {
System.out.println(this.getName() + "觸發了特殊效果,對" + fighter.getName()
+ "造成了" + this.specialDamage + "點額外傷害。");
fighter.loseLife(this.specialDamage);
}
}
}



劍這個類裡定義了傷害值,特殊攻擊的傷害值,特殊攻擊的觸發機率,並且在這裡定義了特殊攻擊的演算法。這樣做有什麼好處呢?看了子類就知道了:

package com.Weapon;

import com.fighter.Fighter;
/*
* 霜之哀傷,攻擊力100,有百分之50造成額外的50點傷害。
* */
public class Frostmourne extends Sword {

public Frostmourne()
{
this.setName("霜之哀傷");
this.setDamage(100);
specialDamage=50;
probability=50;
}

@Override
protected void specialAttack(Fighter fighter) {
super.specialAttack(fighter);
}


}



大家看到了,子類很簡單,只要定義一下名字,傷害,以及特殊攻擊傷害、特殊攻擊機率而已,因為具體演算法實現已經由父類實現了。

同樣的,還有斧類武器:

package com.Weapon;

import java.util.Random;

import com.fighter.Fighter;

//斧類武器有一定機率造成雙倍傷害
public abstract class Axe implements WeaponBehavior {
// 普通傷害
int damage;
String name;
// 特殊攻擊的傷害
int specialDamage;
// 特殊攻擊的觸發機率
int probability;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getDamage() {
return damage;
}

public void setDamage(int damage) {
this.damage = damage;
}

@Override
public void attackWithWeapon(Fighter fighter) {
normalAttack(fighter);
specialAttack(fighter);
}

protected void normalAttack(Fighter fighter) {
System.out.println("用" + this.getName() + "對" + fighter.getName()
+ "造成了" + this.getDamage() + "基本傷害。");
fighter.loseLife(this.getDamage());
}

protected void specialAttack(Fighter fighter) {
Random r = new Random();
//斧子有一定機率造成雙倍傷害
this.specialDamage=damage*2;
int i = r.nextInt(100);
if (i < this.probability) {
System.out.println(this.getName() + "觸發了特殊效果,對" + fighter.getName()
+ "造成了" + this.specialDamage + "點額外傷害。");
fighter.loseLife(this.specialDamage);
}
}
}




package com.Weapon;

import com.fighter.Fighter;
/*
* 公正使者,攻擊力100,有百分之30機率造成雙倍傷害。
* */
public class Axe1 extends Axe {

public Axe1()
{
this.setName("公正使者");
this.setDamage(100);
probability=30;
}

@Override
protected void specialAttack(Fighter fighter) {
super.specialAttack(fighter);
}


}


武器就寫這麼多吧,現在看看Fighter,它就是策略模式定義中的[color=red]使用演算法的客戶[/color]

package com.fighter;

import com.Weapon.WeaponBehavior;

public class Fighter {
private int life;
private String name;
private WeaponBehavior weapon;
public Fighter(String name,WeaponBehavior weapon)
{
this.weapon=weapon;
this.name=name;
this.life=1000;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

public void hit(Fighter fighter)
{
this.weapon.attackWithWeapon(fighter);
}
public int getLife() {
return life;
}
private void setLife(int life) {
this.life = life;
}
public WeaponBehavior getWeapon() {
return weapon;
}
public void setWeapon(WeaponBehavior weapon) {
this.weapon = weapon;
}
public void loseLife(int damage)
{
this.setLife(this.getLife()-damage);
}
public void changeWeapon(WeaponBehavior weapon)
{
System.out.println(this.getName()+"裝備了"+weapon.getName());
this.setWeapon(weapon);
}

}



可以看到,Fighter攻擊的時候只是去呼叫了自身武器的attackWithWeapon(Fighter fighter)方法。這就證實了策略模式的定義,[color=red]定義了演算法簇,分別封裝起來,讓他們之間可以相互替換[/color],這些武器就是演算法簇,使用者只要更換掉自己想要使用的實現類就行了,在呼叫演算法的時候,依然只是呼叫演算法實現的介面。

看下測試類

package com.main;

import com.Weapon.Axe1;
import com.Weapon.Frostmourne;
import com.fighter.Fighter;

public class Main {
public static void main(String[] args) {
Fighter player=new Fighter("player",new Frostmourne());
Fighter computer=new Fighter("computer",new Frostmourne());
player.hit(computer);
System.out.println(computer.getName()+"還剩下"+computer.getLife()+"生命");
player.hit(computer);
System.out.println(computer.getName()+"還剩下"+computer.getLife()+"生命");
//這裡更換了演算法(武器)
player.changeWeapon(new Axe1());
player.hit(computer);
System.out.println(computer.getName()+"還剩下"+computer.getLife()+"生命");
player.hit(computer);
System.out.println(computer.getName()+"還剩下"+computer.getLife()+"生命");
player.hit(computer);
System.out.println(computer.getName()+"還剩下"+computer.getLife()+"生命");
player.hit(computer);
System.out.println(computer.getName()+"還剩下"+computer.getLife()+"生命");
}
}



測試結果:

用霜之哀傷對computer造成了100基本傷害。
霜之哀傷觸發了特殊效果,對computer造成了50點額外傷害。
computer還剩下850生命
用霜之哀傷對computer造成了100基本傷害。
霜之哀傷觸發了特殊效果,對computer造成了50點額外傷害。
computer還剩下700生命
player裝備了公正使者
用公正使者對computer造成了100基本傷害。
computer還剩下600生命
用公正使者對computer造成了100基本傷害。
公正使者觸發了特殊效果,對computer造成了200點額外傷害。
computer還剩下300生命
用公正使者對computer造成了100基本傷害。
computer還剩下200生命
用公正使者對computer造成了100基本傷害。
computer還剩下100生命

相關文章