0
点赞
收藏
分享

微信扫一扫

97 <<java与模式>>之策略模式

西特张 2021-09-21 阅读 93

策略模式属于对象的行为模式。其用意是针对一组算法封装到具有共同接口的独立的类中,从而使得他们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

策略模式是对算法的封装,是把使用算法的责任和算法本身区分开来。为派给不同的对象进行管理。策略模式通常会把一个系列的算法包装到一些列的策略类里面。作为一个抽象策略类的子类。用一句话说,就是: 准备一组算法,并且将每一个算法封装起来,使得他们可以互换。下面就是以一个示意性的实现讲解策略模式实例的结构。


这里模式涉及3个角色
环境(Context)角色:持有一个Strategy的引用
抽象策略(Strategy)角色:这是一个抽象角色,通常有一个接口或抽象类实现。
此角色给出所有的具体的策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
源代码:
环境角色类:

public class Context {
//持有一个具体策略的对象
private Strategy strategy;
/**
* 构造函数,传入一个具体策略对象
* @param strategy 具体策略对象
*/

public Context(Strategy strategy){
this.strategy = strategy;
}
/**
* 策略方法
*/

public void contextInterface(){

strategy.strategyInterface();
}

}


抽象策略类


public interface Strategy {
/**
* 策略方法
*/

public void strategyInterface();
}


具体策略类

public interface Strategy {
/**
* 策略方法
*/

public void strategyInterface();
}

具体的策略类:

public interface Strategy {
/**
* 策略方法
*/

public void strategyInterface();
}

public class ConcreteStrategyB implements Strategy {

@Override
public void strategyInterface() {
//相关的业务
}

}
public class ConcreteStrategyC implements Strategy {

@Override
public void strategyInterface() {
//相关的业务
}

}

使用场景
假设现在要设计一个贩卖各种书籍的电子商务网站的购物车系统。有个最简单的情况就是把所有货品的单价乘以数量。但是实际情况可能比这个要复杂。比如本网站可能对所有的高级会员提供每本20% 的促销折扣。对中级会员提供每本10%的促销折扣。对初级会员没有折扣。
根据描述: 折扣是根据以下的几个算法中的一个进行的:
算法一: 对初级会员没有折扣
算法二: 对中级会员提供10%的促销折扣,
算法三: 对高级会员提供20% 的促销折扣
使用策略模式来实现的结构图如下:



策略模式环境搭建
1 Maven依赖信息:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<!-- sprinboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>






2,MemberStrategy(抽象角色)

package com.taoao.juhe.service;
public interface MemberStrategy {

/**
* 计算图书的价格
* @param booksPrice 图书的原价
* @return 计算折扣后的价格
*/

public double calcPrice(double booksPrice);
}


3,ConcreteStrategy (具体实现角色)

/**
*初级会员的折扣价
*/

@Component
public class PprimaryMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double booksPrice) {
System.out.println("对于初级会员没有折扣");
return booksPrice;
}
}


/**
* 中级会员
*/

@Component
public class IntermediateMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double booksPrice) {
System.out.println("中级会员的折扣为10%");
return booksPrice*0.9;
}
}


/***
* 高级会员价格
*/

@Component
public class AdvanceMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double booksPrice) {
System.out.println("高级会员的折扣为20%");
return booksPrice*0.8;
}
}



PayContextService (上下文)

@Component
public class PayContextStrategy {
public Double calcPrice(double booksPrice) {
PriceEntity priceEntity=priceMapper.priceEntity(booksPrice);
if(priceEntity==null){
return 0d;
}
//获取code,使用spring容器获取实例对象
String code=priceEntity.getCode();
if(Strings.isBlank(code)){
return 0d;
}
//执行实现的方法即可
MemberStrategy memberStrategy=springUtils.getBean(code,MemberStrategy.class);
return memberStrategy.calcPrice(100d);
}
}

SpringUtils

/**
* 使用beanid 获取spring容器中的bean对象
*/

@Component
public class SpringUtils implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}

//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}

//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}

//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}

}







数据库访问层

DROP TABLE IF EXISTS `price`;
CREATE TABLE `price` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`state` int(11) DEFAULT NULL,
`code` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of price
-- ----------------------------
INSERT INTO `price` VALUES ('1', '1', 'pprimaryMemberStrategy');
INSERT INTO `price` VALUES ('2', '2', 'intermediateMemberStrategy');
INSERT INTO `price` VALUES ('3', '3', 'advanceMemberStrategy');


数据库访问层

@Data
public class PriceEntity {
private int id;
private int state;
private String code;
}



Mapper层

package com.taoao.juhe.mapper;

import com.taoao.juhe.entity.CsNumberEntity;
import com.taoao.juhe.entity.PriceEntity;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
public interface PriceMapper {

@Select("select * from price where state=#{booksPrice}")
public PriceEntity priceEntity(@Param(value = "booksPrice") double booksPrice);
}


Controller层

@RestController
public class PayController {
@Autowired
private PayContextStrategy payContextStrategy;

/**
* 找到对应的 会员层级
* @param booksPrice
* @return 折扣后的价格
*/

@RequestMapping("/calcPrice")
public Double calcPrice(double booksPrice){
if(Double.isNaN(booksPrice)){
return 0d;
}
return payContextStrategy.calcPrice(booksPrice);
}

}


举报

相关推荐

0 条评论