Java 状态模式, 策略模式(附代码)

目录

1.什么是状态模式?

1.1卫语句:

1.2状态模式的优缺点:

 1.3思想误区:

2.策略模式:

2.2策略模式的优缺点:

3.总结:


1.什么是状态模式?

        在了解状态模式之前,我们先看一看阿里巴巴开发手册上面,表达异常分支时候的处理方式,:如果非使用 if()...else if()...else...方式表达逻辑,避免后续代码维护困难,请勿超过 3 层。超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,这个时候可能有人就问了什么是卫语句呢?

1.1卫语句:

卫语句就是把复杂的条件表达式拆分成多个条件表达式,减少嵌套。嵌套了好几层的if - then-else语句,转换为多个if语句,实现它的逻辑,这多条的if语句就是卫语句,代码如下。

不使用卫语句:

//不使用卫语句
public class Test {
    public static void main(String[] args) {
        //定义一个字符串
        String you = "ikun";

        //如果你是ikun
        if (you.equals("ikun")){
            return;
        }else {
            //如果你不是ikun
            if (you.equals("noIkun")){
                return;
            }else {
                //如果你是超级ikun
                if (you.equals("superIkun")){
                    return;
                }
            }
        }
    }
}

        可以看到在不使用卫语句的情况下,我们的代码看起来逻辑复杂,在之后的维护之中也更为困难,那么使用卫语句呢? 

使用卫语句: 

//卫语句
public class Test {
    public static void main(String[] args) {
        //定义一个字符串
        String you = "ikun";

        //如果你是ikun
        if (you.equals("ikun")){
            return;
        }
        //如果你不是ikun
        if (you.equals("noIkun")){
            return;
        }
        //如果你是超级ikun
        if (you.equals("superIkun")){
            return;
        }
    }
}

使用卫语句后,我们的代码逻辑清晰,后续维护起来也更为简便。

回到正题那么到底什么是状态模式?

状态模式是一种行为设计模式,它允许对象在内部状态发生改变时改变其行为。该模式将对象的行为封装在不同的状态类中,并通过切换不同的状态来实现不同的行为。这种模式主要用于当对象的行为取决于其内部状态,且在运行时可以动态改变时使用。状态模式提供了一种简洁的方式来管理复杂的条件语句,并将其转化为更加可维护和可扩展的代码结构,同样的在了解代码之前我们也设想个场景:“假如我们现在有个商品,但是这个商品有两个状态(1可以售卖,2不可售卖),在我们状态为1的时候我们可以售卖,但是我们状态为2的时候,不可售卖”,接下来跟着我看看代码怎么实现的。


首先我们需要一个Status接口,里面只有一个saleStatu方法 

Status(状态接口):

//状态接口
public interface Status {
    //卖东西方法
    void saleStatu();
}

接下来我们定义两个类,可以售卖和不可售卖,来实现这个接口

 Sale(可售卖):

//状态为一的时候,(可售卖)
public class Sale implements Status{
    @Override
    public void saleStatu() {
        System.out.println("这件商品可以出售");
    }
}

 NoSale(不可售卖):

//状态为0的时候,(不可售卖)
public class NoSale implements Status{
    @Override
    public void saleStatu() {
        System.out.println("暂不出售");
    }
}

现在类图如下:

 接下来让我们定义一个商品类,来实现调用:

//商品类
public class Goods {
    //状态
    private Status status;

    //传入商品状态方法
    public void Goods(Status status) {
        this.status = status;
    }

    //改变状态方法
    public void doWork(){
        //调用saleStatu方法
        status.saleStatu();
    }
}

 Main(主函数):

//主函数
public class Main {
    public static void main(String[] args) {
        Goods goods = new Goods();
        Integer statu = 1;

        //如果状态为1,则可以售卖
        if (statu == 1){
            goods.Goods(new Sale());
            goods.doWork();
        }
        //如果状态为0,则不能售卖
        if (statu == 0){
            goods.Goods(new NoSale());
            goods.doWork();
        }
    }
}

⚪输出结果:

这件商品可以出售
1.2状态模式的优缺点:

状态模式的优点包括:

  1. 封装了状态:状态模式将每个状态封装在独立的类中,使得状态的变化对客户端透明。这样可以减少对象间的耦合性,提高代码的可维护性和可扩展性。
  2. 符合开闭原则:通过添加新的状态类,我们可以在不修改现有代码的情况下增加新的状态和行为。这符合开闭原则,使得系统更加灵活和可扩展。
  3. 简化了条件语句:状态模式消除了客户端代码中的条件语句,将不同的状态封装在独立的类中。这使得代码更加清晰、简洁,易于理解和维护。
  4. 可以共享状态:如果多个对象共享同一个状态对象,那么状态模式可以帮助我们实现状态对象的共享。这样可以减少内存消耗,并提高系统的性能。

状态模式的缺点包括:

  1. 增加了类的数量:使用状态模式需要定义多个状态类,可能会增加类的数量。如果状态较少或者简单,可以接受,但如果状态较多或者复杂,可能会增加系统的复杂性。
  2. 状态切换开销:由于状态模式在运行时动态切换状态,可能会产生一定的切换开销。如果状态切换频繁,可能会影响系统的性能

总体来说,状态模式是一个强大而灵活的设计模式,可以使对象根据内部状态的变化而改变行为。它提供了封装状态、简化条件语句和实现状态共享的能力。但在使用时需要权衡好类的数量和切换开销,选择合适的状态模式实现。

 1.3思想误区:

        可能大家看了上面这个例子,会说明明这么简单的逻辑为什么需要专门去写两个实现类来实现,其实大家走入了误区,我们这个场景只是个例子,大家可以设想另一个场景:“同样的筛选可售卖商品信息,但是在我们这个场景里要筛选的不仅仅是状态,还有商品的有效期,商品的库存,商品的锁定库存,商品的价格,商品做的特价是否合理,而且我们不同的渠道也会有不同的商品,所以再此我们可以将渠道作为我们的状态,在不同的渠道里去筛选不同渠道从而不同过滤的商品信息,改变了渠道就相当于改变了我们的状态”,特意说这个例子是因为怕大家的思想受到了固化,设计模式并非这么写就只能这么用,正如我上篇文章所说的,我们学设计模式学的不是代码的实现,而是它的整个思想。

2.策略模式:

        可能大家看完策略模式会觉得与状态模式及其相似,但其实并非如此,策略模式更为关注的是具体的实现,而非状态模式的状态,在Java中ThreadPoolExecutor对象中有个接口RejectedExecutionHandler这个接口就使用到了策略模式,那么到底什么是策略模式呢?

        策略模式:策略模式是一种行为型模式,它将对象和行为分开,将行为定义为一个行为接口具体的实现类。策略模式最大的特点是行为的变化,行为之间可以相互替换。每个if判断都可以理解为就是一个策略。本模式使得算法可独立于使用它的用户而变化,那么让我们继续在了解策略模式之前也来设想个场景:"假如老师上课留了个编程作业,但是老师不限制我们使用什么语言,只要能达到最终效果就行",设想完场景接下来让我们关注代码部分。


 与状态模式相同,我们也需要一个接口DoSomething,里面有个方法doWork()

 DoSomeThing(完成任务接口): 

//DoSomething接口
public interface DoSomething {
    //完成作业方法
    void doWork();
}

 DoC(使用c语言来完成作业,实现DoSomething接口):

//使用c来解决问题
public class DoC implements DoSomething{

    //重写完成作业方法
    @Override
    public void doWork() {
        System.out.println("面向过程c,解决问题");
    }
}

 DoJava(使用java来完成作业,实现DoSomething接口):

//使用java来解决问题
public class DoJava implements DoSomething{

    //重写完成作业方法
    @Override
    public void doWork() {
        System.out.println("面向对象Java,解决问题");
    }
}

DoPython(使用Python方法来完成作业,实现DoSomething接口):

//使用Python来解决问题
public class DoPython implements DoSomething{

    //重写完成作业方法
    @Override
    public void doWork() {
        System.out.println("面向对象Python,解决问题");
    }
}

现在类图如下:

 Main(主函数):

//主函数
public class Main {
    public static void main(String[] args) {
        Programmer programmer = new Programmer();
        //选择使用java来解决这个问题
        programmer.Programmer(new DoJava());

        programmer.Do();
    }
}

⚪输出结果:

面向对象Java,解决问题
2.2策略模式的优缺点:

策略模式的优点包括:

  1. 算法的独立性:策略模式将每个算法封装在独立的类中,使得它们可以独立变化而不影响到客户端代码。这使得系统更加灵活,易于维护和扩展。
  2. 可替换性:由于策略模式使用统一的接口定义算法,不同的策略可以相互替换,而不会影响到客户端代码。这使得系统更加可扩展和可重用。
  3. 减少条件语句:策略模式消除了客户端代码中的条件语句,将不同的算法封装在独立的策略类中。这使得代码更加清晰、简洁,易于理解和维护。
  4. 单一职责原则:策略模式将每个算法封装在独立的类中,符合单一职责原则。这使得每个策略类都只关注自己特定的算法实现,代码更加可读和可维护。

策略模式的缺点包括:

  1. 增加类的数量:使用策略模式需要定义多个策略类,可能会增加类的数量。如果策略较少或者简单,可以接受,但如果策略较多或者复杂,可能会增加系统的复杂性。
  2. 客户端需要了解不同的策略类:客户端需要了解不同的策略类,并在运行时选择合适的策略。这增加了客户端代码的复杂性,但也提供了更大的灵活性和可替换性。
  3. 策略切换开销:由于策略模式在运行时动态选择算法,可能会产生一定的切换开销。如果算法切换频繁,可能会影响系统的性能。

总体来说,策略模式是一个强大而灵活的设计模式,可以提供可替换、可扩展和可维护的算法实现。但在使用时需要权衡好类的数量和切换开销,选择合适的策略模式实现。

3.总结:

        不知不觉更到现在也更新了8个设计模式了,希望大家在学习新的设计模式的时候也不要忘记以前学过的设计模式,学会温故而知新,反复揣摩,反复实验,不要把知识仅仅停留在理论阶段,用代码说话,最好是自己能够理解到这个思想,最后希望大家在未来都能成为自己心中想要成为的自己。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值