DesignPattern

项目地址:youlookwhat/DesignPattern 

简介: Java 设计模式归纳 (观察者、工厂、单例、策略、适配器、命令、装饰者、外观、模板方法、状态).

更多:作者   提 Bug

标签:

参照 Hongyang 的 CSDN 博客所写。如有错误欢迎指正,如有侵权,请联系我删除。

Java 设计模式(观察者模式、工厂模式、单例模式、策略模式、命令模式、装饰者模式、外观模式、模板方法模式、状态模式)

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

设计模式分为三种类型,共 23 种:

  • 创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
  • 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
  • 行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。

Blog Catalogue:

  • 1. 设计模式 观察者模式(Observer Pattern) 以微信公众服务为例

  • 2. 设计模式 工厂模式(Factory Pattern) 从卖肉夹馍说起

  • 3. 设计模式 单例设计模式(Singleton Pattern) 完全解析

  • 4. 设计模式 策略模式(Strategy Pattern) 以角色游戏为背景

  • 5. 设计模式 适配器模式(Adapter Pattern) 以手机充电器为例

  • 6. 设计模式 命令模式(Command Pattern) 管理智能家电

  • 7. 设计模式 装饰者模式(Decorator Pattern) 带你重回传奇世界

  • 8. 设计模式 外观模式(Facade Pattern) 一键电影模式

  • 9. 设计模式 模版方法模式(Template Method Pattern) 展现程序员的一天

  • 10. 设计模式 状态模式(State Pattern) 以自动售货机为例

Source Code

    1. Observer
    1. Factory
    1. Singleton
    1. Strategy
    1. Adapter
    1. Command
    1. Decorator
    1. Facade
    1. Template Method
    1. State

Project Picture

        

Pattern Analysis

1. 观察者模式

定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

  • 对于 JDK 或者 Andorid 中都有很多地方实现了观察者模式,比如 XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener 不一定是观察者模式,因为观察者模式是一种一对多的关系,对于 setXXXListener 是 1 对 1 的关系,应该叫回调。

  • 专题接口:Subject.java ;

       /*** 注册一个观察者*/public void registerObserver(Observer observer);/*** 移除一个观察者*/public void removeObserver(Observer observer);/*** 通知所有观察者*/public void notifyObservers();
    
  • 3D 服务号的实现类:ObjectFor3D.java

      @Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {int index = observers.indexOf(observer);if (index >= 0) {observers.remove(index);}}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(msg);}}/*** 主题更新信息*/public void setMsg(String msg) {this.msg = msg;notifyObservers();}
    
  • 所有观察者需要实现此接口:Observer.java

      public ObserverUser1(Subject subject) {subject.registerObserver(this);}@Overridepublic void update(String msg) {Log.e("-----ObserverUser1 ", "得到 3D 号码:" + msg + ", 我要记下来。");}
    
  • 最后测试:ObserverActivity.java

      // 创建服务号objectFor3D = new ObjectFor3D();// 创建两个订阅者observerUser1 = new ObserverUser1(objectFor3D);observerUser2 = new ObserverUser2(objectFor3D);// 两个观察者,发送两条信息objectFor3D.setMsg("201610121 的 3D 号为:127");objectFor3D.setMsg("20161022 的 3D 号为:000");
    

2. 工厂模式

简单列一下这个模式的家族:

  • 1、静态工厂模式

    • 这个最常见了,项目中的辅助类,TextUtil.isEmpty 等,类+静态方法。
  • 2、简单工厂模式(店里买肉夹馍)

    • 定义:通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
    • 根据类型直接创建肉夹馍:SimpleRoujiaMoFactory.java

      public RoujiaMo creatRoujiaMo(String type) {RoujiaMo roujiaMo = null;switch (type) {case "Suan":roujiaMo = new ZSuanRoujiaMo();break;case "La":roujiaMo = new ZLaRoujiaMo();break;case "Tian":roujiaMo = new ZTianRoujiaMo();break;default:// 默认为酸肉夹馍roujiaMo = new ZSuanRoujiaMo();break;}return roujiaMo;
      }
      
  • 3、工厂方法模式(开分店)

    • 定义:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。
    • 对比定义:

      • 1、定义了创建对象的一个接口:public abstract RouJiaMo sellRoujiaMo(String type);
      • 2、由子类决定实例化的类,可以看到我们的馍是子类生成的。
      • 提供创建肉夹馍店抽象方法:RoujiaMoStore.java
      public abstract RoujiaMo sellRoujiaMo(String type);
      
    • 具体实现抽象方法:XianRoujiaMoStore.java
    • 分店依旧使用简单工厂模式:XianSimpleRoujiaMoFactory.java
  • 4、抽象工厂模式(使用官方提供的原料)

    • 定义:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。
    • 对比定义:
      • 1、提供一个接口:public interface RouJiaMoYLFactroy
      • 2、用于创建相关的或依赖对象的家族 public Meat createMeat();public YuanLiao createYuanliao();我们接口用于创建一系列的原材料。
    • 创建用于提供原料的接口工厂:RoujiaMoYLFactory.java
    • 各自分店实现接口,完成原料提供:XianRoujiaMoYLFoctory.java
    • 准备时,使用官方的原料:RoujiaMo.java

      ```java /**

    • 准备工作 */ public void prepare(RoujiaMoYLFactory roujiaMoYLFactory) {
       Meet meet = roujiaMoYLFactory.creatMeet();YuanLiao yuanLiao = roujiaMoYLFactory.creatYuanLiao();Log.e("---RoujiaMo:", "使用官方的原料 ---" + name + ": 揉面-剁肉-完成准备工作 yuanLiao:"+meet+"yuanLiao:"+yuanLiao);
      

      } ```

3. 单例设计模式

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例

  • 定义:只需要三步就可以保证对象的唯一性

    • (1) 不允许其他程序用 new 对象
    • (2) 在该类中创建对象
    • (3) 对外提供一个可以让其他程序获取该对象的方法
  • 对比定义:
    • (1) 私有化该类的构造函数
    • (2) 通过 new 在本类中创建一个本类对象
    • (3) 定义一个公有的方法,将在该类中所创建的对象返回
  • 饿汉式[可用]:SingletonEHan.java
  • 含懒汉式[双重校验锁 推荐用]:SingletonLanHan.java

    ```java private SingletonLanHan() {} private static SingletonLanHan singletonLanHanFour; public static SingletonLanHan getSingletonLanHanFour() {

          if (singletonLanHanFour == null) {synchronized (SingletonLanHan.class) {if (singletonLanHanFour == null) {singletonLanHanFour = new SingletonLanHan();}}}return singletonLanHanFour;
    

    }


- 内部类[推荐用]:[SingletonIn.java](https://raw.githubusercontent.com/youlookwhat/DesignPattern/master/app/src/main/java/com/example/jingbin/designpattern/singleton/inclass/SingletonIn.java)
- 枚举[推荐用]:[SingletonEnum.java](https://raw.githubusercontent.com/youlookwhat/DesignPattern/master/app/src/main/java/com/example/jingbin/designpattern/singleton/enums/SingletonEnum.java)### 4. 策略模式
> 策略模式:定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。- 以创建游戏角色为例子:- 最初的游戏角色的父类:[Role.java](https://raw.githubusercontent.com/youlookwhat/DesignPattern/master/app/src/main/java/com/example/jingbin/designpattern/strategy/old/Role.java)- 发现有重复代码后,重构后的父类:[Role.java](https://raw.githubusercontent.com/youlookwhat/DesignPattern/master/app/src/main/java/com/example/jingbin/designpattern/strategy/better/Role.java)- 总结:- 1、封装变化(把可能变化的代码封装起来)- 2、多用组合,少用继承(我们使用组合的方式,为客户设置了算法)- 3、针对接口编程,不针对实现(对于 Role 类的设计完全的针对角色,和技能的实现没有关系)- 最后测试:创建角色:```javaRoleA roleA = new RoleA("---A");roleA.setiDisplayBehavior(new DisplayYZ()).setiAttackBehavior(new AttackXL()).setiDefendBehavior(new DefendTMS()).setiRunBehavior(new RunJCTQ());roleA.display();// 样子roleA.attack();// 攻击roleA.run();// 逃跑roleA.defend();// 防御

5. 适配器模式

定义:将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以相互合作。这个定义还好,说适配器的功能就是把一个接口转成另一个接口。

  • 以充电器为实例: 手机充电器一般都是 5V 左右吧,咱天朝的家用交流电压 220V,所以手机充电需要一个适配器(降压器)
  • 一部手机: Mobile.java
  • 手机依赖一个提供 5V 电压的接口: V5Power.java
  • 我们拥有的是 220V 家用交流电: V220Power.java
  • 适配器,完成 220V 转 5V 的作用:V5PowerAdapter.java
  • 最后测试:给手机冲个电:

      Mobile mobile = new Mobile();
    V5Power v5Power = new V5PowerAdapter(new V200Power());
    mobile.inputPower(v5Power);
    

6. 命令模式

定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(简化: 将请求封装成对象,将动作请求者和动作执行者解耦。)

  • 需求:最近智能家电很火热,假设现在有电视、电脑、电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要有非常强的扩展性。
  • 1、家电的 API:Door.java
  • 2、把命令封装成类:
    • 统一的命令接口:Command.java
    • 家电实现该接口:DoorOpenCommand.java
  • 3、遥控器:ControlPanel.java
  • 4、定义一个命令,可以干一系列的事情:QuickCommand.java

    QuickCommand quickCloseCommand = new QuickCommand(new Command[]{new LightOffCommand(light), new ComputerOffCommand(computer), new DoorCloseCommand(door)});
    controlPanel.setCommands(6, quickOpenCommand);
    controlPanel.keyPressed(6);
    
  • 5、遥控器面板执行:CommandActivity.java

    controlPanel.setCommands(0, new DoorOpenCommand(door));// 开门
    controlPanel.keyPressed(0);
    

7. 装饰者模式

装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。

  • 先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。这里还体现了一个原则:类应该对扩展开放,对修改关闭。

  • 需求:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:

  • 1、装备的超类:IEquip.java
  • 2、各个装备的实现类:
    • eg:武器的实现类: ArmEquip.java
  • 3、装饰品的超类(装饰品也属于装备):IEquipDecorator.java
  • 4、装饰品的实现类:

    • eg:蓝宝石的实现类(可累加): BlueGemDecorator.java
  • 5、最后测试:计算攻击力和查看描述:

      Log.e("---", "一个镶嵌 2 颗红宝石,1 颗蓝宝石的靴子: ");IEquip iEquip = new RedGemDecotator(new RedGemDecotator(new BlueGemDecotator(new ShoeEquip())));Log.e("---", "攻击力:" + iEquip.caculateAttack());Log.e("---", "描述语:" + iEquip.description());
    

8. 外观模式

定义:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。其实就是为了方便客户的使用,把一群操作,封装成一个方法。

  • 需求:我比较喜欢看电影,于是买了投影仪、电脑、音响、设计了房间的灯光、买了爆米花机,然后我想看电影的时候,我需要一键观影和一键关闭。
  • 每个设备类的开关等操作:
    • eg: 爆米花机:PopcornPopper.java
  • 电影院类:HomeTheaterFacade.java

      /*** 一键观影*/public void watchMovie() {computer.on();light.down();popcornPopper.on();popcornPopper.makePopcorn();projector.on();projector.open();player.on();player.make3DListener();}
    
    • 最后测试:一键观影:

      new HomeTheaterFacade(computer, light, player, popcornPopper, projector).watchMovie();
      

9. 模板方法模式

定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

  • 需求:简单描述一下:本公司有程序猿、测试、HR、项目经理等人,下面使用模版方法模式,记录下所有人员的上班情况
  • 模板方法模式中的三类角色
    • 1、具体方法(Concrete Method)
    • 2、抽象方法(Abstract Method)
    • 3、钩子方法(Hook Method)
  • 工人的超类:Worker.java

      // 具体方法public final void workOneDay() {Log.e("workOneDay", "-----------------work start----------------");enterCompany();work();exitCompany();Log.e("workOneDay", "-----------------work end----------------");}// 工作  抽象方法public abstract void work();// 钩子方法public boolean isNeedPrintDate() {return false;}private void exitCompany() {if (isNeedPrintDate()) {Log.e("exitCompany", "---" + new Date().toLocaleString() + "--->");}Log.e("exitCompany", name + "---离开公司");}
    
  • 程序员实现类(可得知时间):ITWorker.java

      /*** 重写父类的此方法,使可以查看离开公司时间*/@Overridepublic boolean isNeedPrintDate() {return true;}
    
  • 最后测试:

    • 查看所有人员的工作情况:

        QAWorker qaWorker = new QAWorker("测试人员");qaWorker();HRWorker hrWorker = new HRWorker("莉莉姐");hrWorker.workOneDay();...
      
    • 查看程序猿离开公司的时间:

        ITWorker itWorker = new ITWorker("jingbin");itWorker.workOneDay();
      

10. 状态模式

定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

  • 定义又开始模糊了,理一下,当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的。

  • 需求:已自动售货机为例(有已投币、未投币等状态和投币、投币等方法)

  • 最初实现待改进的售货机:VendingMachine.java
  • 改进后的售货机(更具有延展性):VendingMachineBetter.java

      // 放钱public void insertMoney() {currentState.insertMoney();}// 退钱public void backMoney() {currentState.backMoney();}// 转动曲柄public void turnCrank() {currentState.turnCrank();if (currentState == soldState || currentState == winnerState) {currentState.dispense();//两种情况会出货}}// 出商品public void dispense() {Log.e("VendingMachineBetter", "---发出一件商品");if (count > 0) {count--;}}// 设置对应状态public void setState(State state) {this.currentState = state;}
    
  • 状态的接口:State.java

  • 对应状态的接口实现类:
    • eg: 中奖状态:WinnerState.java
    • eg: 售卖状态:SoldState.java
  • 改进后的售货机测试:

      // 初始化售货机,且里面有 3 个商品VendingMachineBetter machineBetter = new VendingMachineBetter(3);machineBetter.insertMoney();machineBetter.turnCrank();
    

Download

  • DesignPattern.apk

Reference

  • http://blog.csdn.net/lmj623565791/article/category/2206597

Thanks

  • CSDN:张鸿洋
  • CSDN:dmk877

Java 设计模式归纳(观察者、工厂、单例、策略、适配器、命令、装饰者、外观、模板方法、状态相关推荐

  1. Java 设计模式归纳(观察者、工厂、单例,进阶学习资料

    observerUser1 = new ObserverUser1(objectFor3D); observerUser2 = new ObserverUser2(objectFor3D); // 两 ...

  2. Java设计模式透析之 —— 单例(Singleton)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8860649 写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上 ...

  3. 设计模式--常用8个设计模式 单例-策略-责任链-装饰者-迭代器模式-观察者模式-常用设计模式

    1创建型的设计模式-主要有单例模式和工厂模式 对象的创建会消耗掉系统的很多资源,所以单独对对象的创建进行研究,从而能够高效地创建对象就是创建型模式要探讨的问题 2结构型的设计模式-主要有代理模式和适配 ...

  4. Ruby设计模式透析之 —— 单例(Singleton)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8868758 此为Java设计模式透析的拷贝版,专门为Ruby爱好者提供的,不熟悉R ...

  5. java饿汉式有啥作用,Java面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式(饿汉式和懒汉式)?...

    什么是单例设计模式? 单例设计模式就是一种控制实例化对象个数的设计模式. 为什么要使用单例设计模式? 使用单例设计模式可以节省内存空间,提高性能.因为很多情况下,有些类是不需要重复产生对象的.如果重复 ...

  6. 【设计模式】-创造篇-单例

    单例定义 单例模式(Singleton)是一种非常简单且容易理解的设计模式.顾名思义,单例即单一的实例,确切地讲就是指在某个系统中只存在一个实例,同时提供集中.统一的访问接口,以使系统行为保持协调一致 ...

  7. java设计模式3种工厂模式

    java设计模式3种工厂模式 2010-01-08 16:06:36|  分类: JAVA技术|举报|字号 订阅 下载LOFTER客户端 工厂模式分为三种: Simple Factory模式 专门定义 ...

  8. 设计模式是什么鬼(单例)

    转自:设计模式是什么鬼(单例) 之前我们讲过面向对象以及封装.继承.多态三大特性,底子打好了那我们就把设计模式一个个拆开来看看到底都是神些什么鬼,我们先从简单的单例说起吧.单例,顾名思义,整个系统其实 ...

  9. IOS设计模式第二篇之单例设计模式

    现在我们的组件已经有组织了.你需要从其他的地方得到数据,你也可以创建一个API类管理数据这个下个设计模式单例里面介绍. 这个单例设计模式确保这个类仅仅拥有一个实例,并且为这个实例提供一个全局的访问点. ...

最新文章

  1. JavaScript中,this的绑定规则
  2. 在MySQL查询山东省男生信息_mysql查询语句
  3. 洛谷P2057 【SHOI2007】善意的投票
  4. SQL查询所有客人的第一次用餐时间
  5. 小程序添加动画效果--遇到的问题
  6. 星露谷物语json_《星露谷物语》1.5版本更新细节公开 已上线PC
  7. 从os.cpus()来分析nodejs源码结构
  8. mfc窗口右下角如何显示一个三角形图案_以C4D制作金属碳笼为例:安利一个友好的三维制图软件...
  9. 毕业论文中的调查问卷怎样设计以及分析?
  10. 腾讯视频qlv格式怎么转换成mp4在手机上播放
  11. [转]使用CSS和JQuery,模拟超链接点击 原文:http://www.cnblogs.com/return8023/archive/2012/05/19/2509177.html...
  12. DSP TMS320C5509A 控制DDS AD9854芯片驱动
  13. 《IT项目经理成长手记》读后有所思
  14. 微信跑腿小程序怎么做
  15. 电商资讯 | 黑鲨大幅裁员,2022年游戏手机销量大跳水,降幅近40%
  16. 表格table中的td标签中的内容太多,影响整体外观,不美观。将一部分内容隐藏起来,用省略号代替
  17. 移臂调度算法java_C语言 磁盘调度模拟
  18. SpringBoot整合JavaMail通过阿里云企业邮箱发送邮件
  19. PC(Ubuntu)和树莓派实现无秘ssh
  20. 国内程序员的Linux开发平台-Deepin

热门文章

  1. Android 定位c++异常
  2. HTML文档组成的三要素是,电视机原理期末考试试题(含答案)(九江学院)
  3. vue滚动摇号抽奖组件
  4. 单曲循环 翻译_单曲循环。用英语怎么说?
  5. ZOJ 1204 Additive equations
  6. 最好用的录屏工具Bandicam (班迪录屏)
  7. [附源码]计算机毕业设计Python美发店会员管理系统(程序+源码+LW文档)
  8. Java面试题基础篇(一)
  9. vue路由跳转控制台出现:vue-router.esm.js?8c4f:2316 TypeError: Cannot read properties of undefined (reading ‘$c
  10. 力扣61. 旋转链表(转vector三次翻转、成环解环)