0
点赞
收藏
分享

微信扫一扫

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

西特张 2021-09-21 阅读 98

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

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


这里模式涉及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 条评论