发表于: 2018-03-28 22:03:31

2 649


今天完成的事情:
今天主要研究了一下关于策略模式。一开始看着听难懂的,但是认真研究了一下,发现就是一个比较简单的东西。
首选什么是策略模式,从网上搜到的解释是:
策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
策略模式的优点有:策略模式提供了管理相关的算法族的办法、策略模式提供了可以替换继承关系的办法、使用策略模式可以避免使用多重条件转移语句。


看不懂这玩意,然后我又找了找别的解释:

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
应用实例:
        1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
        2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
        3、JAVA AWT 中的 LayoutManager。
优点:
     1、算法可以自由切换。
     2、避免使用多重条件判断。
     3、扩展性良好。
缺点:
     1、策略类会增多。
     2、所有策略类都需要对外暴露。
使用场景:
       1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。                    2、一个系统需要动态地在几种算法中选择一种。
       3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
这个模式涉及到三个角色:
        ●  环境(Context)角色:持有一个Strategy的引用。
        ●  抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
        ●  具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。


这个大概的将策略模式全部做了一个很好的阐释,但一开始,我还是有些迷迷糊糊,然后我就大概的搜了一下别人demo,找到一篇很好的教程:

项目结构大概如下:
上面三个箭头分别指向:1.策略控制器。  决定具体使用什么策略的一个类。
                     2 .策略接口。 策略接口是决定策略具体方法的。
                     3.被封装的具体算法。策略就需要实现策略接口,每一个策略实现的方法相同,但是每一个策略具体执行方法的方式不同。
换句话说就是策略控制器决定具体使用哪种策略,策略接口决定策略的大体方法,策略类决定如何使用对应的算法达到目的。


下面是具体代码:

策略接口:
import java.math.BigDecimal;
//计算价格的接口
public interface Strategy {
//计算价格
public  BigDecimal calculatePrice();
}


策略实现类:

空账户nullMember:
@Service("nullMember")
public class nullMember implements Strategy {
    @Override
    public BigDecimal calculatePrice() {
        return new BigDecimal("200");//------------------------------此处输出价格
    }
}
普通账户generalMember:
@Service("generalMember")
public class GeneralMember implements Strategy {
    @Override
    public BigDecimal calculatePrice() {
        return new BigDecimal("100");//------------------------------此处输出价格
    }
}
VIP账户VipMember:
@Service("vipMember")
public class VipMember implements Strategy {
    @Override
    public BigDecimal calculatePrice() {
        return new BigDecimal("80");//------------------------------此处输出价格
    }
}
超级账户superMember:
@Service("superMember")
public class SuperMember implements Strategy {
    @Override
    public  BigDecimal calculatePrice() {
        return new BigDecimal("1");//------------------------------此处输出价格
    }
}


策略管理类StrategyContext:

@Component
public class StrategyContext {
    private final Map<String, Strategy> strategyMap = new ConcurrentHashMap<>();//---------------Map
    @Autowired
    public StrategyContext(Map<String, Strategy> strategyMap) {
        this.strategyMap.clear();
        strategyMap.forEach((k, v) -> this.strategyMap.put(k, v));
        //-------------------内嵌入lamada表达式:(k, v) -> this.strategyMap.put(k, v)
    }
    public BigDecimal calculatePrice(String memberLevel) {
        if (!StringUtils.isEmpty(memberLevel)) {
            return strategyMap.get(memberLevel).calculatePrice();
        }
        return null;
    }
}


Spring配置文件:

<!-- 激活MVC功能 -->
<mvc:annotation-driven/>
<!--使用default服务器处理静态资源-->
<mvc:default-servlet-handler/>
<!-- 扫描该包路径下所有使用注解的类型 -->
<context:component-scan base-package="com.jnshu.*"/>
<!--处理jsp的ViewResolver-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
启动Tomcat,简单看一下效果:


可以看到,我们在输入不同的类名的时候,程序会执行与类名对应的方法,然后返回给程序对应的值。

也就是在不同的情况下唤醒对应的策略,从而实现分而治之的功能。
看懂上面的代码真的很花费了一番心思,后来才发现,所谓的策略模式,就是利用策略控制类的控制方法,
去调用一批实现了同一个接口并重写了同一个方法的类。


然后上面的那个教程的作者,同时在函数中使用的Map集合和拉姆达表达式,而且是运用Map去获取到程序中的bean这么骚包的操作,看得我一愣一愣的。

为了搞懂作者干了啥,我又重新学了一遍关于lamada表达式和集合的内容。

首先是lamada表达式。

什么是lamada表达式?
首先介绍一个概念叫“函数式接口”(functional interfaces)。对于任意一个Java接口,如果接口中只定义了唯一一个方法,那么这个接口就称之为“函数式接口”。
简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。


也就是在弄懂什么是lamada表达式之前,先要明白什么是匿名函数,或者说匿名方法。

“函数式接口”(functional interfaces)。对于任意一个Java接口,如果接口中只定义了唯一一个方法,那么这个接口就称之为“函数式接口”。



(params) -> expression//-----------------------------表达式
(params) -> statement//------------------------------声明
(params) -> { statements }
简单示例如下:
() -> System.out.println("In Java8, Lambda expression rocks !!") )//输入一段语句
(k, v) -> this.strategyMap.put(k, v)//向strategyMap中插入值
() -> { for (int i = 0; i < 100; i++) System.out.println(i); }//表达式中有一个循环的代码块
然后在和东霖讨论的时候,又学到了一个关于使用类的技巧NEW.
有时候,我们想使用类里的某个方法,同时又不想创建一次类。就可以使用new函数去创建一个一次性的类来完成操作。
首先我们先看看上面的超级账户类,然后建立一个新建一个类,写一个main方法,方法中写入下面这句话,点击运行:
System.out.println(new SuperMember().calculatePrice());
可以看到效果如下:
明天计划的事情:根据策略模式调整上传方法,然后整合项目,完成任务七的项目搭建。
遇到的问题:
1.如何使用Spring配置策略控制类实现xml配置。
解决思路:拆开工具类,使其匹配策略模式。明天试试看。
收获:
学会了lamada表达式。
进度:
任务开始时间:2018年03月18日
预计demo时间:2018年03月30日



返回列表 返回列表
评论

    分享到