java设计模式之策略模式

1.简介

为了应对需求的变更,我们需要采用一些设计模式来降低类之间的耦合度。
策略模式将可变的部分从程序中抽象分离成算法接口,在该接口下分别封装一系列算法实现。

2.适用场景

策略模式主要适用于以下场景:
① 相关的类仅仅是行为差异,例如要给鸭子类添加飞行功能(在鸭子类下继承了很多种类的鸭子,不同鸭子的飞行不一定相同)
② 在运行时选取不同的算法变体,例如支付功能,选择不同的银行进行支付。
③ 通过条件语句在多个分支中选取其一。

3.一个策略模式示例——打印机的例子

某公司专门销售各种打印机,销售打印机时都有一定的折扣让利给顾客,但折扣计算的方法有很多种,如:不打折;每台减扣固定的金额;按售价的5%打折等等,且折扣计算方法可能发生变化。

①声明策略接口Discount,声明打折方法discount

package strategy;

public interface Discount {
	void discount();

}

②各种Discount的实现类,实现不同的打折方式

无折扣:

package strategy.disIpl;

import strategy.Discount;

public class noDiscount implements Discount {

	public void discount(){
		System.out.println("没有折扣!");
	}
}

折扣5%:

package strategy.disIpl;

import strategy.Discount;

public class PercentDis implements Discount {

	public void discount(){
		System.out.println("折扣5%!");
	}
}

③编写抽象类打印机类,方便不同种类打印机的继承

在抽象类中,声明一个Discount接口的实例,从而使它可以有打折这个行为。

package strategy;
import strategy.Discount;

public abstract class Printer {

   
   private Discount dis;
   public abstract void display();
   
   public Printer(){
   	
   }
   
   public void setDis(Discount discount){
   	dis = discount;
   }
   
   public void discount(){
   	dis.discount();
   }
}

④编写具体类实现抽象类Printer并注入策略实现算法

Printer1:

package strategy;

import strategy.disIpl.*;

public class Printer1 extends Printer {

	public Printer1(){
		super();
		super.setDis(new noDiscount());
	}
	
	public void display(){
		System.out.println("这是一号打印机:");
	}
}

Printer2:

package strategy;

import strategy.disIpl.*;

public class Printer2 extends Printer {

	public Printer2(){
		super();
		super.setDis(new PercentDis());
	}
	
	public void display(){
		System.out.println("这是二号打印机:");
	}
}

⑤test

package strategy;

public class PrinterTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Printer1 printer1 = new Printer1();
		printer1.display();
		printer1.discount();
		
		Printer2 printer2 = new Printer2();
		printer2.display();
		printer2.discount();
	}

}

4.类图

java设计模式之策略模式

当然这个类图里还比上面的代码多了一种折扣方式和一种打印机。

5.总结

从上面我们很容易看出来这个方法很易于修改,我们要再增加打印机或者更改折扣方式都是非常容易的。

其实上面打印机的例子里除了策略模式我们还有两种方式可以实现:
①直接在父类中实现其中一种打折方法,在子类中如果和父类不同则进行覆写。但是这样的话万一忘记覆写就会出错。
②在父类中添加一种打折的抽象方法,但不实现。←增加了子类的代码量,如果有很多很多很多打印机都用的同一种打折方法,就增加了很多不必要的代码。

策略模式相对好地解决了这个问题,但它也有缺点,那就是增加了对象的数量。