设计模式(2)策略模式 (模式讲解+应用)

雾凇枚举
• 阅读 3650

博客新址,这里更有趣

目录

  1. 策略模式

  2. 为什么使用策略模式?

  3. 策略模式应用实例

策略模式

策略模式:建立行为族,将不同的行为分别封装,同时彼此可相互替代,算法的变化可以独立于使用者。
优点:提高了可复用性,将行为和使用者解耦出来
缺点:增加了编写代码工作量

为什么使用策略模式

通过一个游戏的例子我们可以更好的说明这个问题,我们的游戏中有很多的人物,这个时候,我们定义一个基础游戏角色类,然后不同的角色将会有不同的技能,所以其攻击行为和防御行为在不同的角色中是不同的,其单位攻击所造成的伤害和攻击的特效也是不同的,如果按照传统的方式,我们首先想到的写法可能是这样子的。

//基类,具有攻击和防御行为,所有游戏角色继承自这个基类
class People{
    People(){

    }
//攻击
    public void attck(){

    }
//防御
    public void defense(){

    }
}
//法师角色

class Master extends People{
    Master(){

    }
    public void attck(){
        造成魔法伤害
    }
    public void defense(){
        抵御魔法攻击
    }

}
//剑客角色
class Swordsman extends People{
    Swordsman(){

    }
    public void attck(){
        造成物理伤害
    }
    public void defense(){
        抵御物理攻击
    }
}

这样子来看完全可行,我们需要什么角色实例的时候只需要new一个即可,但是我们的游戏中的角色往往是有很多的,而不只是简单这几种的。当我们为了改善游戏体验进一步吸引用户,所以需要对游戏中的角色的攻击增加特效或者是对防御增加某种特殊防御,或者是该角色的攻击方式和防御方式都发生了变化,这个时候我们就需要对每一个角色类进行查找,找到那些角色有这种攻击方式和防御方式,然后打开对其进行修改,工作将变得很繁琐,同时对原有的类进行修改也进一步增加了我们犯错的几率。如何改善这种状况呢?这个时候我们需要考虑,这其中那些东西是变的,而那些东西是固定的,然后封装变化的。这也正是设计的一个原则找出那些变化的将他们独立出来,不要和那些不需要变化的混在一起

所以我们想到将这些变化的行为,攻击和防御进行封装起来,将一些不会变化的比如,姓名,性别设置,更新方法与之孤立起来。将行为进行封装,便于我们后期的需求变更时,对项目进行更新,那么我们想到的就是设置不同的行为类,然后通过委托的方式,在角色的内部发生其真实行为。那么我们可以写出下面的代码。

abstract class People{
    Attackable attckable;
    Denfenseable denfenseable;
    public void setAttckMethond(Attackable attckable){
        this.attckable = attckable;
    }
    public void setDefenseMethond(Denfenseable denfenseable){
        this.denfenseable = denfenseable;
    }
    public void attck(){
        attckable.invoke();

    }
    public void defense(){
        denfenseable.invoke();
    }
    public abstract void haveSex();
    More Methond.....
}
//法师
class Master extends People{
    Master(){

    }
    public void haveSex(){
        System.out.println("Come on");
    }

}
//剑客
class Swordsman extends People{
     Swordsman(){

    }
    public void haveSex(){
        System.out.println("ya mie die")
    }
}
//定义攻击接口
public interface Attackable{
    public void invoke();
}
// 定义防御接口
public interface Denfenseable{
    public void invoke();
}
//实现了攻击接口的秒杀全场攻击
public class KillAll implements Attackable{
    public void invoke(){
        System.out.println("Kill All");
    }
}
//实现了防御接口的抵御任何攻击接口
public class DenfenseAnyAttack implements Denfenseable{
    public void invoke(){
        System.out.println("Denfense All");
    }
}

将变化的攻击和防御行为单独拿出来作为接口,然后在基类中通过委托的形式,借助多态,来实现相应的攻击,防御方式,同时设置了set方法,使得其扩展性进一步增强。当我们修改英雄的攻击行为和防御行为只需要通过set方法即可,如果对攻击和防御行为的表现形式进行修改,通过找到相应的行为类修改即可,借助委托,多态,实现了彻底的将对象和行为进行解耦。

依赖注入:通常我们可以通过set方法,构造函数来将我们所依赖的对象,通过接口或者是父类的形式注入进去。内部借助委托机制实现相应的功能。

策略模式应用实例

在我们开法,我们所使用的类库中,有哪些是通过策略模式来实现的呢?
在Android的动画中,Animation有一个方法为setInterpolator() 熟悉Android开发的一定知道其作用,用来设置一个插值器,其作用是用来控制动画开始结束等一些特效,而其实现就是使用了策略模式。

package android.animation;
 
public interface Interpolator {

    float getInterpolation(float input);
}

有一个插值器的接口,然后各种不同类型的插值器通过实现接口来实现不同的动画特效。实现Interpolator接口的类有

AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速

AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速

AnticipateInterpolator 开始的时候向后然后向前甩

AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值

BounceInterpolator 动画结束的时候弹起

CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线

DecelerateInterpolator 在动画开始的地方快然后慢

LinearInterpolator 以常量速率改变

OvershootInterpolator 向前甩一定值后再回到原来位置

举一个例子

package android.view.animation;
 
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
 
public class AccelerateInterpolator implements Interpolator {
    private final float mFactor;
    private final double mDoubleFactor;
 
    public AccelerateInterpolator() {
        mFactor = 1.0f;
        mDoubleFactor = 2.0;
    }
 
    public AccelerateInterpolator(float factor) {
        mFactor = factor;
        mDoubleFactor = 2 * mFactor;
    }
 
    public AccelerateInterpolator(Context context, AttributeSet attrs) {
        TypedArray a =
            context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator);
 
        mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);
        mDoubleFactor = 2 * mFactor;
 
        a.recycle();
    }
 
    public float getInterpolation(float input) {
        if (mFactor == 1.0f) {
            return input * input;
        } else {
            return (float)Math.pow(input, mDoubleFactor);
        }
    }
}

Animation源码

public abstract class Animation implements Cloneable {
    Interpolator mInterpolator;
    
    public void setInterpolator(Interpolator i) {
         mInterpolator = i;
     }
 
    public boolean getTransformation(long currentTime, Transformation outTransformation) {
        final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
        applyTransformation(interpolatedTime, outTransformation);
       // ... ...
    }
      protected void ensureInterpolator() {
         if (mInterpolator == null) {
             mInterpolator = new AccelerateDecelerateInterpolator();
         }
     }
 
}

总结:通过对于源码的分析,不难发现其和游戏角色设定的相似之处,实现一个接口,然后不同行为实现该接口,使用者通过set方法,以接口的形式,实现具体实例的依赖注入。从而实现相应的功能。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
责任链和策略设计模式-基于Java编程语言
责任链和策略设计模式这两种设计模式非常实用,下面简单介绍一下我对这两种设计模式的理解和它们在Spring框架源码中的应用。
Wesley13 Wesley13
3年前
java设计模式详细讲解
原文链接:java设计模式详细讲解观察者模式(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.blogchina.cn%2Fblog%2Fguopengfei%2Fhome%2F270%2F1575725711626"java设计模式详细讲解观察者模式")如果想要更加
Wesley13 Wesley13
3年前
00_设计模式之语言选择
设计模式之语言选择设计模式简介背景设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式(Designpattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的
Wesley13 Wesley13
3年前
Java 设计模式系列(十二)策略模式(Strategy)
Java设计模式系列(十二)策略模式(Strategy)策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。一、策略模式的结构策略模式是对算
Wesley13 Wesley13
3年前
Java描述设计模式(22):策略模式
本文源码:GitHub·点这里(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fgithub.com%2Fcicadasmile%2Fmodelarithmeticparent)||GitEE·点这里(https://gitee.com/cicadasmile/modela
Wesley13 Wesley13
3年前
如何利用策略模式避免冗长的 if
策略模式。在实际的项目开发中,这个模式也比较常用。最常见的应用场景是,利用它来避免冗长的ifelse或switch分支判断。不过,它的作用还不止如此。它也可以像模板模式那样,提供框架的扩展点等等。对于策略模式。本篇我们讲解策略模式的原理和实现,以及如何用它来避免分支判断逻辑。后续我会通过一个具体的例子,来详细讲解策略模式的应用场景以及真正的设计意图
京东云开发者 京东云开发者
7个月前
设计模式-策略模式
作者:京东工业孙磊一、概念策略模式(StrategyPattern)也称为(PolicyParttern)。它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变换,不会影响到使用算法的客户。策略模式属性行为模式。策略模式结构图\二、实际
京东云开发者 京东云开发者
4个月前
设计模式-策略模式
作者:京东工业孙磊一、概念策略模式(StrategyPattern)也称为(PolicyParttern)。它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变换,不会影响到使用算法的客户。策略模式属性行为模式。策略模式结构图\二、实际
京东云开发者 京东云开发者
2个月前
设计模式-策略模式
作者:京东工业孙磊一、概念策略模式(StrategyPattern)也称为(PolicyParttern)。它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变换,不会影响到使用算法的客户。策略模式属性行为模式。策略模式结构图\二、实际