设计模式笔记(七)——状态模式 原

1. 回忆上一次的观察者模式中出现的问题

l  晴天——开心上班

l  下雨——打着雨伞上班

l  雾霾——带着消毒面具上班

l  冰雹——带着三级头盔上班

l  狂风——拖着大石头上班

l  暴雪——披着被子上班

使用了非常多的if,else-if,else

2. 是什么——定义

类的行为是基于它的状态改变的。状态模式使得允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

3. 为什么——特点

对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。

将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

4. 什么时候用——适用性

代码中包含大量与对象状态有关的条件语句。

5. UML图

6. 怎么用——使用方法

需求:

    改造观察者模式中的复杂分支结构

改造步骤:

    1. 将每种天气看做一个状态

    2. 将“天气”变成抽象类,实际的每种天气是对应的子类

    3. 让关联关系的实体依天气的变化而变化

    4. 给每种天气设置一个if-else判断,如果当前天气与本“类class”对应的天气相同,则进入分支结构,否则,将当前天气传入下一个要判断的天气类,直到碰见null为止(核心)

    5. 使用模板方法模式,抽取出当前天气类的执行状态代码(改良)

public abstract class AbstractWeather {
    private String name;
    private AbstractWeather nextWeather;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public AbstractWeather getNextWeather() {
        return nextWeather;
    }
    public void setNextWeather(AbstractWeather nextWeather) {
        this.nextWeather = nextWeather;
    }
    
    //状态模式的核心方法
    public abstract void give(String currentWeather);
}

晴天:

public class Sun extends AbstractWeather {
    public Sun() {
        this.setName("晴天");
        this.setNextWeather(new Wind());
    }

    @Override
    public void give() {
        if (this.getName().equals(currentWeather)) {
            System.out.println("今天是晴天,老子要高高兴兴的去上学。。。");
        }else {
            getNextWeather().give(currentWeather);
        }
    }
}

刮风:

public class Wind extends AbstractWeather {
    public Wind() {
        this.setName("刮风");
        this.setNextWeather(new Snow());
    }

    @Override
    public void give() {
        if (this.getName().equals(currentWeather)) {
            System.out.println("今天刮大风,老子要拖着大石头去上学。。。");
        }else {
            getNextWeather().give(currentWeather);
        }
    }
}

发现新的问题:

两个子类的give方法里都有相同代码!可以使用模板方法模式改进!

改进之后:

public class Sun extends AbstractWeather {
    public Sun() {
        this.setName("晴天");
        this.setNextWeather(new Wind());
    }

    @Override
    public void doMethod() {
        System.out.println("今天是晴天,老子要高高兴兴的去上学。。。");
    }
}

public class Wind extends AbstractWeather {
    public Wind() {
        this.setName("狂风");
        this.setNextWeather(new Rain());
    }

    @Override
    public void doMethod() {
        System.out.println("今天刮大风了,老子要拖着大石头去上学。。。");
    }
}

public class Rain extends AbstractWeather {
    public Rain() {
        this.setName("下雨");
        this.setNextWeather(new Snow());
    }
    
    @Override
    public void doMethod() {
        System.out.println("今天下雨了,老子要打着伞去上学。。。");
    }
}

学生类中只需要一句代码即可:

    public void notifyWeather(String weather) {
        new Sun().give(weather);
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI研习社

用在数据科学上的 Python:你可能忘记的 8 个概念

如果你在编程的时候发现自己一遍又一遍的搜索同一个问题、概念或者语法,那么你并不孤单。

971
来自专栏大数据挖掘DT机器学习

[笔记]使用Python一步一步地来进行数据分析

原文 http://www.cnblogs.com/nxld/p/6058998.html 你已经决定来学习Python,但是你之前没有编程经验。因此,你常常...

7276
来自专栏JAVA高级架构开发

面向对象编程,再见!

作为程序员,你是使用函数式编程还是面向对象编程方式?在本文中,拥有 10 多年软件开发经验的作者从面向对象编程的三大特性——继承、封装、多态三大角度提出了自己的...

3020
来自专栏java学习

每日一练(2017/5/22)

Java基础 | 数据库 | Android | 学习视频 | 学习资料下载 课前导读 ●回复"每日一练"获取以前的题目! ●答案公布时间:为每期发布题目的第二...

3428
来自专栏HTML5学堂

只有JS基础扎实的攻城狮,才解得出的“密码”

HTML5学堂-码匠:虽然很不想面对,但是明天,的确是节后工作的开始,今天就一边解密一边“适应”一下代码吧! Tips:如下的四道题目,是基于几家公司的面试真题...

39810
来自专栏C语言及其他语言

【每日一题】尼科彻斯定理

题目描述 验证尼科彻斯定理,即:任何一个正整数的立方都可以写成一串连续奇数的和。 输入 任一正整数 输出 该数的立方分解为一串连续奇数的和 样例输入 13 样例...

3369
来自专栏养码场

趣读 | 怎样算是「风骚」的代码?

关于Unlambda语言,David Madore是这个语言的发明人,他于1976年8月3日生于法国,其是法国-加拿大籍数学家和计算机科学爱好者)。在unlam...

902
来自专栏HansBug's Lab

1054: [HAOI2008]移动玩具

1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1272  Solv...

2506
来自专栏chafezhou

学习Python,怎能不懂点PEP呢?

作者:豌豆花下猫,某985高校毕业生, 兼具极客思维与人文情怀 。公众号Python猫, 专注python技术、数据科学和深度学习,力图创造一个有趣又有用的学习...

1311
来自专栏趣谈编程

冒泡排序

面试官: 写一个冒泡排序吧 冒泡排序是一个比较经典和简单的排序算法,今天我们从从算法本身,时间复杂度以及稳定性方面来看看冒泡排序,这些方面也是研究其他排序算法的...

20110

扫码关注云+社区

领取腾讯云代金券