设计模式的艺术 行为型模式之策略模式

前言

条条大路通罗马,很多时候为了达到目标可供选择的路径不止一条,在软件开发中也会存在这样的情况,为了某一个功能有多条途径,每一条途径对应一种算法,为了灵活的选择解决途径,策略模式就应运而生了

什么是策略模式 Strategy Pattern

定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,策略模式也被称之为政策模式,策略模式是一种对象行为型模式

策略模式的优点

(1)、策略模式提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择算法或者行为,也可以灵活的增加新的算法或行为

(2)、策略模式提供了管理相关的算法族的办法,策略类的等级结构定义了一个算法或者行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码

(3)、策略模式提供了一种可以替换继承关系的方法,如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用和算法本身就混合在了一起,不符合单一职责原则,决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换

(4)、使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或者行为的逻辑或行为本身的实现逻辑混合在了一起,将它们都以硬编码的方式放入同一个庞大的多重条件选择中,比直接继承环境类的办法还要原始和落后

(5)、策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便的复用这些策略类

策略模式的缺点

(1)、客户端必须知道所有的策略类,并自行决定使用哪一个策略类,这就意味着客户端必须理解这些算法的区别,以便适时的选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况

(2)、策略模式将造成系统产生很多的具体策略类,任何细小的变化都将会导致系统要增加一个新的具体策略类

(3)、无法同时在客户端使用多个策略类。也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能然后再使用另一个策略类完成剩下的功能的情况

策略模式的使用场景

(1)、系统需要动态的在几种算法中选择一种,那么可以将这些算法封装到一个个的具体算法中,而这些具体算法类都是一个抽象算法类的子类,换言之,这些具体算法类均有统一的接口,根据里氏替换原则和面向对象的多态性,客户端可以使用任何一个具体算法类,并只需要维持一个数据类型是抽象算法类的对象

(2)、一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现,此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句。

(3)、不希望客户端知道复杂,与算法相关的数据结构,在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性和安全性

策略模式的具体实现

目录结构

抽象状态类

package com.company;

//抽象状态类
public abstract class AccountState {
    protected Account acc;

    public abstract void deposit(double amount);

    public abstract void withdraw(double amount);

    public abstract void computerInterest();

    public abstract void stateCheck();
}

具体状态类

package com.company;

//正常状态:具体状态类
public class NormalState extends AccountState {

    public NormalState(Account account) {
        this.acc=account;
    }

    public NormalState(AccountState overDraftState) {
        this.acc=overDraftState.acc;
    }

    @Override
    public void deposit(double amount) {
            acc.setBalance(acc.getBalance()+amount);
            stateCheck();
    }

    @Override
    public void withdraw(double amount) {
            acc.setBalance(acc.getBalance()-amount);
            stateCheck();
    }

    @Override
    public void computerInterest() {
        System.out.println("正常装填,无须支付利息");
    }

    @Override
    public void stateCheck() {
        if(acc.getBalance()>-2000 && acc.getBalance()<=0){
            acc.setState(new OverDraftState(this));
        }else if(acc.getBalance()==-2000){
            acc.setState(new RestrictedState(this));
        }else if(acc.getBalance()<-2000) {
            System.out.println("操作受限!");
        }
    }
}
package com.company;

//透支状态:具体状态类
public class OverDraftState extends  AccountState {
    public OverDraftState(AccountState state) {
        this.acc=state.acc;
    }

    @Override
    public void deposit(double amount) {
        acc.setBalance(acc.getBalance()+amount);
        stateCheck();
    }

    @Override
    public void withdraw(double amount) {
        acc.setBalance(acc.getBalance()-amount);
        stateCheck();
    }

    @Override
    public void computerInterest() {
        System.out.println("计算利息!");
    }

    @Override
    public void stateCheck() {
        if(acc.getBalance()>0){
            acc.setState(new NormalState(this));
            acc.setState(new RestrictedState(this));
        }else if(acc.getBalance()==-2000){
        }else if(acc.getBalance()<-2000){
            System.out.println("操作受限!");
        }
    }
}
package com.company;

//受限状态:具体状态类
public class RestrictedState extends AccountState {

    public RestrictedState(AccountState state) {
        this.acc=state.acc;
    }


    @Override
    public void deposit(double amount) {
        acc.setBalance(acc.getBalance()+amount);
        stateCheck();
    }

    @Override
    public void withdraw(double amount) {
            System.out.println("账号受限,取款失败");
    }

    @Override
    public void computerInterest() {
        System.out.println("计算利息!");
    }

    @Override
    public void stateCheck() {
        if(acc.getBalance()>0){
            acc.setState(new NormalState(this));
        }else if(acc.getBalance()>-2000){
            acc.setState(new OverDraftState(this));
        }
    }
}

环境类

package com.company;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

//银行账户:环境类
public class Account {
    private AccountState state;  //维持一个对抽象状态对象的引用
    private String owner;   //开户名
    private double balance;  //账户余额s

    public Account(String owner, double balance) {
        this.owner = owner;
        this.balance = balance;
        this.state = new NormalState(this);  //设置初始状态
        System.out.println(this.owner + "开户,初始金额为" + balance);
        System.out.println("------------------------");

    }

    public void deposit(double amount) {
        System.out.println(this.owner + "存款" + amount);
        state.deposit(amount);  //调用状态对象的deposit()方法
        System.out.println("现在余额为" + this.balance);
        System.out.println("现在账户状态为" + this.state.getClass().getName());
        System.out.println("---------------------------");
    }

    public void withdraw(double amount) {
        System.out.println(this.owner + "取款" + amount);
        state.withdraw(amount);  //调用状态对象的withdraw()方法
        System.out.println("现在余额为" + this.balance);
        System.out.println("现在账户状态为" + this.state.getClass().getName());
        System.out.println("-------------------------------");
    }

    public void computeInterest() {
        state.computerInterest();  //调用状态对象的computeInterest()方法
    }

    public AccountState getState() {
        return state;
    }

    public void setState(AccountState state) {
        this.state = state;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

测试端

package com.company;

public class Main {

    public static void main(String[] args) {
    Account acc=new Account("段誉",0.0);
    acc.deposit(1000);
    acc.withdraw(200);
    acc.deposit(1000);
    acc.withdraw(4000);
    acc.withdraw(1000);
    acc.computeInterest();
    }
}

转载请注明出处,掌声送给社会人

猜你喜欢

转载自blog.csdn.net/SCDN_CP/article/details/83341583
今日推荐