文章内容主要参考了刘伟主编的《设计模式(第2版)》,同时也结合了自己的一些思考和理解,希望能帮到大家。
本篇讲解策略模式。非常常见,也非常简单容易理解。
策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。
这个模式使得我们可以在根据环境或者条件的不同选择不同的策略来完成该任务。将解决途径进行封装有利于我们对解决方式的增加或删除。符合开闭原则。
软件公司为某电影院开发了一套影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票打折方式,具体打折方案如下:
(1) 学生凭学生证可享受票价8折优惠;
(2) 年龄在10周岁及以下的儿童可享受每张票减免10元的优惠;
(3) 影院VIP用户除享受票价半价优惠外还可进行积分。
关于上面情景的类图(具体分析在下面)
抽象策略类Discount
public interface Discount{ public double calculate(double price); }
三个具体策略类
//学生优惠 public class StudentDiscount implements Discount{ public double calculate(double price){ System.out.println("学生票:"); return price*0.8; } } //儿童优惠 public class ChildDiscount implements Discount{ public double calculate(double price){ System.out.println("儿童票:"); return price-10; } } //VIP优惠 public class VIPDiscount implements Discount { public double calculate(double price){ System.out.println("VIP票:"); System.out.println("增加积分!"); return price*0.5; } }
环境类买票MovieTicket
public class MovieTicket { private double price; private Discount discount; public void setPrice(double price){ this.price = price; } public void setDiscount(Discount d){ this.discount = d; } public double getPrice(){ return discount.calculate(price); } }
客户端Client
public class Client { public static void main(String[] args) { MovieTicket mt; Discount discount; discount = (Discount)XMLUtil.getBean();//相当于获取特定的对象,如VIPDdiscount类 mt = new MovieTicket(discount); mt.setPrice(100); System.out.println("优惠后的价格:"+mt.getPrice()); } }
工具类XMLUtil帮助我们读取XML文件并返回我们想要的内容给我们。
import javax.xml.parsers.*; import org.w3c.dom.*; import org.xml.sax.SAXException; import java.io.*; public class XMLUtil { //该方法用于从XML配置文件中提取对应对象,并返回对象 public static String getBean() { try { //创建文档对象 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("config.xml")); //获取包含类名的文本节点 NodeList nl = doc.getElementsByTagName("name"); Node classNode = nl.item(0).getFirstChild(); String name = classNode.getNodeValue().trim(); return name; } catch(Exception e) { e.printStackTrace(); return null; } } }
接着就是我们的配置文件config.xml
<?xml version="1.0"?> <config> <name>VIPDiscount</name> </config>
我们通过将买票的优惠方式进行封装,对应于一个类,那么这里就可以免去了过多的ifelse语句,当然给每一个策略添加一个总的抽象类是必须的。之后环境类根据抽象类编程即可。这就是策略模式非常的简单。
模式类图:
本篇文章主要介绍设计模式的策略模式,非常简单,但是不要和状态模式弄混淆了!