策略模式是一种行为型模式,它将对象和行为分开,将行为定义为 一个行为接口和 具体行为的实现
设计原则
假设在我们的商城系统中,需要实现一个优惠促销功能。其中优惠促销有以下几种规则。
对于这样的一个需求,我们该怎么实现呢?有同学可能会说了,加上几个if else
就好了,接着噼里啪啦一顿操作,
if(user.role.equals("新用户")){
}else if(user.role.equale("满减卷")){
}else if(user.role.equale("折扣卷")){
}
这种写法是很简单,但仔细想想,这样写可能会有如下方面的问题。
如果优惠规则多了,类和方法会变得非常庞大,难以维护。而且维护和扩展都需要修改已有的代码,这样违反了开闭原则。
在不同时期,同样条件下的优惠力度可能也不一样。如在平常时期,新注册用户首单立减10元,在周年庆期间,新注册用户首单立减15元,过了周年庆,又变回首单立减10元。通过上边代码来实现这样的效果,需要频繁的修改if else中的代码,这样的切换方式会非常麻烦。
在我们生活中比较常见的应用模式有:
1、电商网站支付方式,一般分为银联、微信、支付宝,可以采用策略模式
2、电商网站活动方式,一般分为满减送、限时折扣、包邮活动,拼团等可以采用策略模式
案例:使用策略模式+工厂模式实现选择支付功能(微信支付,支付宝,银行卡)
package demo;
/**
*
* 使用策略模式+工厂模式实现选择支付功能(微信支付,支付宝,银行卡)
* 传统方式展示
*/
public abstract class Payment {
/**
* 默认微信支付
*/
public void wxPayMent(){
System.err.println("我是微信支付");
}
}
package demo;
public class WxPayMent extends Payment{
@Override
public void wxPayMent() {
//默认微信支付
super.wxPayMent();
}
}
package demo;
public class YlPayMent extends Payment{
/**
* 同理支付宝
*/
@Override
public void wxPayMent() {
System.err.println("我是银联支付");
}
}
package demo;
/**
* 支付宝支付
*/
public class ZfbPayMent extends Payment{
/**
* 显然我是支付宝支付,而父类是微信支付,这里使用父类的就不合理了,需要重写父类方法
*/
@Override
public void wxPayMent() {
System.err.println("我是支付宝支付");
}
}
package demo;
public class Test {
public static void main(String[] args) {
//使用支付宝支付
Payment payment =new ZfbPayMent();
payment.wxPayMent();
//使用银联支付
Payment ylPayMent = new YlPayMent();
ylPayMent.wxPayMent();
//默认支付
Payment wxPayMent = new WxPayMent();
wxPayMent.wxPayMent();
}
}
/**
*
* 使用策略模式+工厂模式实现选择支付功能(微信支付,支付宝,银行卡)
* 传统方式展示
*/
public interface Payment {
//提供支付方法,具体是什么支付由子类实现
public void PayMent();
}
public class WxPayMent implements Payment{
@Override
public void PayMent() {
System.err.println("我是微信支付");
}
}
public class YlPayMent implements Payment{
/**
* 同理支付宝
*/
@Override
public void PayMent() {
System.err.println("我是银联支付");
}
}
/**
* 支付宝支付
*/
public class ZfbPayMent implements Payment{
/**
* 显然我是支付宝支付,而父类是微信支付,这里使用父类的就不合理了,需要重写父类方法
*/
@Override
public void PayMent() {
System.err.println("我是支付宝支付");
}
}
/**
* 客户端使用者
*/
public class Client {
//需要使用支付方法
public Payment payment;
public void setPayment(Payment payment) {
this.payment = payment;
}
//提供使用支付方法
public void clientPayment(){
//代码实现了分离
payment.PayMent();
}
}
//使用微信提供的支付方法
public class WxClient extends Client{
public WxClient(){
payment = new WxPayMent();
}
}
//使用支付宝提供的支付方法
public class ZfbClient extends Client{
public ZfbClient(){
payment = new ZfbPayMent();
}
}
public class Test {
public static void main(String[] args) {
/**
* 动态运行修改
*/
Client client = new Client();
Payment wxPayMent = new WxPayMent();
client.setPayment(wxPayMent);
client.clientPayment();
System.err.println("我动态被修改了");
ZfbPayMent zfbPayMent = new ZfbPayMent();
client.setPayment(zfbPayMent);
client.clientPayment();
/**
* 选择一种支付方式(这里应该由前端传过来,再使用工厂模式进行处理选择,不然这里还得用if判断,可维护性差)
* if("微信支付"){
* Client wxClient = new WxClient();
* }else if("支付宝支付"){
* Client wxClient = new ZfbClient();
* }
*/
Client wxClient = new WxClient();
wxClient.clientPayment();
}
}
/**
* 简单工厂模式
*/
public class SimplePayMentFactory {
public static Client getPayMent(String payment){
if("微信支付".equals(payment)){
return new WxClient();
}else if("支付宝支付".equals(payment)){
return new ZfbClient();
}else{
return null;
}
}
}
/**
* 简单工厂模式
* 使用工厂模式处理选择支付方式(前端传入具体支付方式)
*/
Client client2 = SimplePayMentFactory.getPayMent("支付宝支付");
client2.clientPayment();
/**
* 总结 使用设计模式在以上代码中优化了多重判断和new对象了,
* 客户端只需要传入你需要的,其他什么都不用管了
*/
策略模式提供了对“开闭原则”的完美支持,用户可以在不 修改原有系统的基础上选择算法或行为,也可以灵活地增加 新的算法或行为。
策略模式提供了管理相关的算法族的办法。
策略模式提供了可以替换继承关系的办法。
使用策略模式可以避免使用多重条件转移语句。
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
策略模式将造成产生很多策略类,可以通过使用享元模式在一 定程度上减少对象的数量