import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.net.URL;
class MovieTicket{
private double price;
private Discount discount;
public void setPrice(double price) {
this.price = price;
}
public void setDiscount(Discount discount) {
this.discount = discount;
}
public double getPrice(){
return discount.calculate(this.price);
}
}
interface Discount{
public double calculate(double price);
}
class StudentDiscount implements Discount{
public double calculate(double price) {
System.out.println("学生票打折");
return 0.8*price;
}
}
class VIPDiscount implements Discount{
public double calculate(double price) {
System.out.println("VIP打折");
System.out.println("赠送积分");
return 0.5*price;
}
}
class ChildrenDiscount implements Discount{
public double calculate(double price) {
System.out.println("儿童票打折");
return price-10;
}
}
class XMLUtil{
public static Object getBean(){
URL url = StragetyPattern.class.getClassLoader().getResource("config.xml");
try {
DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=dFactory.newDocumentBuilder();
Document doc;
doc=builder.parse(new File(url.toURI()));
NodeList nl=doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
public class StragetyPattern {
public static void main(String[] args){
MovieTicket mt=new MovieTicket();
double originalPrice=60.0;
double currentPrice;
mt.setPrice(originalPrice);
System.out.println("原始价格为:"+originalPrice);
System.out.println("---------------------------");
Discount discount=(Discount)XMLUtil.getBean();
mt.setDiscount(discount);
currentPrice=mt.getPrice();
System.out.println("折价后价格为:"+currentPrice);
}
}
<?xml version="1.0" encoding="utf-8" ?>
<config>
<className>VIPDiscount</className>
</config>
写代码时总会出很多的if…else,或者case。如果在一个条件语句中又包含了多个条件语句就会使得代码变得臃肿,维护的成本也会加大,而策略模式就能较好的解决这个问题,本篇博客就带你详细了解策略模式。
策略模式的定义和使用场景
定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化。
分析下定义,策略模式定义和封装了一系列的算法,它们是可以相互替换的,也就是说它们具有共性,而它们的共性就体现在策略接口的行为上,另外为了达到最后一句话的目的,也就是说让算法独立于使用它的客户而独立变化,我们需要让客户端依赖于策略接口。
策略模式的使用场景:
1.针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
2.需要安全地封装多种同一类型的操作时;
3.出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。
UML类图
这个模式涉及到三个角色:
环境(Context)角色:持有一个Strategy的引用。
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
策略模式用于算法的自由切换和扩展。
1 提供了对开闭原则的支持,不修改原有系统基础上选择增加算法
2 提供了管理相关的算法族的方法。策略类的等级结构定义了一个算法或行为族,恰当使用继承吧公共代码移到抽象策略中,避免重复代码。
3 算法的使用和算法类分开
4 避免多重条件选择
缺点
1 只适用于客户端知道所有的算法和行为的情况
2 产生很多具体策略类
3 无法同时使用同一个策略类,不支持用一个策略完成部分功能后在使用另一个策略类完成生育功能