设计模式的分类
我们都知道有 23 种设计模式,这 23 种设计模式可分为如下三类:
- 创建型模式(5 种):单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
- 结构型模式(7 种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式(11 种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式系列文章传送门
什么是策略模式
策略模式是一个行为行设计模式,定义了一系列算法,并将每一个算法封装起来做为一个策略类,使的它们之间可以相互替换,策略模式可以让算法独立于客户端。
策略模式的组成部分
- 上下文类:也叫环境类,它持有一个策略类的引用,通过策略类的方法来执行具体的算法,上下文类会提供一个统一的接口,可以让客户端访问不同的策略。
- 抽象策略类:定义了一个统一的接口,让不同的策略类实现实现这个接口,从而实现具体的算法。
- 具体策略类:实现了抽象策略类,并重写了抽象策略类中定义的统一接口,也就是实现了具体的算法,不同的具体策略类有不同的算法实现,它们之间可以相互替换,使得上下文类在运行时可以动态地改变策略。
策略模式案例演示
我们以春节回家购买火车票为案例,我们购买火车票可以选择 12306 官网购票、携程网购票、去哪儿网购票,假设张三、李四、王五分别要从三个客户端来完成买票,我们使用策略模式使用不同客户端买票。
BuyTicketsStrategy(抽象策略类)
BuyTicketsStrategy 买票抽象策略类,定义了买票方法,代码如下:
java
public interface BuyTicketsStrategy {
//出发地 目的地
void buyTickets(String user, String startPoint, String destination);
}
BuyTicketsContext(上下文类)
BuyTicketsContext 上下文类,买票上下文类持有了一个买票抽象策略类对象,并调用了买票方法,代码如下:
java
public class BuyTicketsContext {
//用户
private String user;
//出发地
private String startPoint;
//目的地
private String destination;
//买票策略类
private BuyTicketsStrategy buyTicketsStrategy;
public BuyTicketsContext(String user, String startPoint, String destination, BuyTicketsStrategy buyTicketsStrategy) {
this.user = user;
this.startPoint = startPoint;
this.destination = destination;
this.buyTicketsStrategy = buyTicketsStrategy;
}
//调用具体的策略类来买票
public void buyTickets() {
System.out.println(user + "买票出发了买票策略上下文");
buyTicketsStrategy.buyTickets(user, startPoint, destination);
}
}
OfficialWebsiteBuyTicket(具体策略类)
OfficialWebsiteBuyTicket 12306 官网买票策略类,实现了买票抽象策略类,并重新了买票方法,代码如下:
java
public class OfficialWebsiteBuyTicket implements BuyTicketsStrategy{
@Override
public void buyTickets(String user, String startPoint, String destination) {
System.out.println("用户:" + user + "使用去12306官网买票,出发地:" + startPoint + ",目的地:" + destination);
}
}
XieChengBuyTicket(具体策略类)
XieChengBuyTicket 携程买票策略类,实现了买票抽象策略类,并重新了买票方法,代码如下:
java
public class XieChengBuyTicket implements BuyTicketsStrategy {
@Override
public void buyTickets(String user, String startPoint, String destination) {
System.out.println("用户:" + user + "使用携程网买票,出发地:" + startPoint + ",目的地:" + destination);
}
}
QuNaErBuyTicket(具体策略类)
QuNaErBuyTicket 去哪儿买票策略类,实现了买票抽象策略类,并重新了买票方法,代码如下:
java
public class QuNaErBuyTicket implements BuyTicketsStrategy {
@Override
public void buyTickets(String user, String startPoint, String destination) {
System.out.println("用户:" + user + "使用去哪儿网买票,出发地:" + startPoint + ",目的地:" + destination);
}
}
BuyTicketClient(具体策略类)
客户端触发买票操作,代码如下:
java
public class BuyTicketClient {
public static void main(String[] args) {
//官网买票
new BuyTicketsContext("张三", "北京", "上海", new OfficialWebsiteBuyTicket()).buyTickets();
//携程买票
new BuyTicketsContext("张三", "北京", "上海", new XieChengBuyTicket()).buyTickets();
//去哪儿买票
new BuyTicketsContext("张三", "北京", "上海", new QuNaErBuyTicket()).buyTickets();
}
}
买票结果如下:
powershell
张三买票出发了买票策略上下文
用户:张三使用去12306官网买票,出发地:北京,目的地:上海
张三买票出发了买票策略上下文
用户:张三使用携程网买票,出发地:北京,目的地:上海
张三买票出发了买票策略上下文
用户:张三使用去哪儿网买票,出发地:北京,目的地:上海
结果符合预期。
假设我们没有使用策略模式,如果要实现张三、李四、王五分别要从三个客户端来完成买票,则需要如下实现:
java
public class NoStrategyClient {
public static void main(String[] args) {
String user = "张三";
if ("张三".equals(user)) {
//官网买票
OfficialWebsiteBuyTicket officialWebsiteBuyTicket = new OfficialWebsiteBuyTicket();
officialWebsiteBuyTicket.buyTickets("张三", "北京", "上海");
} else if ("李四".equals(user)) {
//携程买票
OfficialWebsiteBuyTicket officialWebsiteBuyTicket = new OfficialWebsiteBuyTicket();
officialWebsiteBuyTicket.buyTickets("李四", "北京", "上海");
} else if ("王五".equals(user)) {
//去哪儿买票
OfficialWebsiteBuyTicket officialWebsiteBuyTicket = new OfficialWebsiteBuyTicket();
officialWebsiteBuyTicket.buyTickets("王五", "北京", "上海");
}
}
}
可以看到如果不使用策略模式,则需要使用 if else 来完成,可见策略模式可以帮我们消除 if else,让代码看起来更优雅。
策略模式的优缺点
优点:
- 策略模式实现了算法的定义和使用的分离,将不同的算法封装成相互独立的策略类,可以让算法可以独立变化,这提高了代码的灵活性和可维护性。
- 扩展性良好,新加一个策略只需要新增一个策略类即可,无需修改其他代码。
- 避免了条件语句的使用,代码更优雅。
优点:
- 策略模式增加了代码量,增加了抽象策略类,上下文类,让系统变得更复杂。
- 客户端需要知道具体的策略类,才知道如何选择,也就是说将算法的选择放在了客户端进行,增加了客户端代码的复杂性。
策略模式的使用场景
- 当业务需要动态的在几种算法中选择一种时,可将种算法封装到策略类中,使用策略模式来实现。
- 消除条件语句 if else。
总结:本篇简单分享了策略模式的概念及使用场景,并且使用多渠道买票场景来演示策略模式的使用,希望可以能够帮助不太熟悉策略模式的朋友加深对策略模式的理解。
如有不正确的地方欢迎各位指出纠正。