一、空对象模式(Null Object Pattern)

1、概念

在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。

2、实例

我们将创建一个定义操作(在这里,是客户的名称)的 AbstractCustomer 抽象类,和扩展了 AbstractCustomer 类的实体类。工厂类 CustomerFactory 基于客户传递的名字来返回 RealCustomer 或 NullCustomer 对象。演示类 NullPatternDemo,我们的演示类使用 CustomerFactory 来演示空对象模式的用法。

(1)、创建一个抽象类

public abstract classAbstractCustomer {protectedString name;public abstract booleanisNil();public abstractString getName();

}

(2)、扩展一个执行操作的实体类

public class RealCustomer extendsAbstractCustomer {publicRealCustomer(String name) {this.name =name;

}

@OverridepublicString getName() {returnname;

}

@Overridepublic booleanisNil() {return false;

}

}

(3)、扩展一个不做任何实现的空对象类

public class NullCustomer extendsAbstractCustomer {

@OverridepublicString getName() {return "Not Available in Customer Database";

}

@Overridepublic booleanisNil() {return true;

}

}

(4)、创建 CustomerFactory 类

public classCustomerFactory {public static final String[] names = {"Rob", "Joe", "Julie"};public staticAbstractCustomer getCustomer(String name){for (int i = 0; i < names.length; i++) {if(names[i].equalsIgnoreCase(name)){return newRealCustomer(name);

}

}return newNullCustomer();

}

}

(5)、使用 CustomerFactory,基于客户传递的名字,来获取 RealCustomer 或 NullCustomer 对象

public classNullPatternDemo {public static voidmain(String[] args) {

AbstractCustomer customer1= CustomerFactory.getCustomer("Rob");

AbstractCustomer customer2= CustomerFactory.getCustomer("Bob");

AbstractCustomer customer3= CustomerFactory.getCustomer("Julie");

AbstractCustomer customer4= CustomerFactory.getCustomer("Laura");

System.out.println("Customers");

System.out.println(customer1.getName());

System.out.println(customer2.getName());

System.out.println(customer3.getName());

System.out.println(customer4.getName());

}

}

(5)、演示结果

1 Customers2 Rob3 Not Available in Customer Database4 Julie5 Not Available in Customer Database

二、策略模式(Strategy Pattern)

1、概念

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

2、简介

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

关键代码:实现同一个接口。

优点:

(1)、算法可以自由切换。

(2)、避免使用多重条件判断。

(3)、扩展性良好。

缺点:

(1)、策略类会增多。

(2)、所有策略类都需要对外暴露。

使用场景:

(1)、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

(2)、一个系统需要动态地在几种算法中选择一种。

(3)、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

3、实例

我们将创建一个定义活动的 Strategy 接口和实现了 Strategy 接口的实体策略类。Context 是一个使用了某种策略的类。演示类 StrategyPatternDemo,我们的演示类使用 Context 和策略对象来演示 Context 在它所配置或使用的策略改变时的行为变化。

(1)、创建一个接口

public interfaceStrategy {public int doOperation(int num1, intnum2);

}

(2)、创建接口的实现类

public class OperationAdd implementsStrategy{

@Overridepublic int doOperation(int num1, intnum2) {return num1 +num2;

}

}

public class OperationSubstract implementsStrategy{

@Overridepublic int doOperation(int num1, intnum2) {return num1 -num2;

}

}

public class OperationMultiply implementsStrategy{

@Overridepublic int doOperation(int num1, intnum2) {return num1 *num2;

}

}

(3)、创建 Context 类

public classContext {privateStrategy strategy;publicContext(Strategy strategy){this.strategy =strategy;

}public int executeStrategy(int num1, intnum2){returnstrategy.doOperation(num1, num2);

}

}

(4)、使用 Context 来查看当它改变策略 Strategy 时的行为变化。

public classStrategyPatternDemo {public static voidmain(String[] args) {

Context context= new Context(newOperationAdd());

System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

context= new Context(newOperationSubstract());

System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

context= new Context(newOperationMultiply());

System.out.println("10 * 5 = " + context.executeStrategy(10, 5));

}

}

(5)、演示结果

1 10 + 5 = 15

2 10 - 5 = 5

3 10 * 5 = 50

三、模板模式(Template Pattern)

1、概念

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

2、简介

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

主要解决:一些方法通用,却在每一个子类都重新写了这一方法。

何时使用:有一些通用的方法。

如何解决:将这些通用算法抽象出来。

关键代码:在抽象类实现,其他步骤在子类实现。

优点:

(1)、封装不变部分,扩展可变部分。

(2)、提取公共代码,便于维护。

(3)、行为由父类控制,子类实现。

缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

使用场景:

(1)、有多个子类共有的方法,且逻辑相同。

(2)、重要的、复杂的方法,可以考虑作为模板方法。

注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。

3、实例

我们将创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法。演示类 TemplatePatternDemo,我们的演示类使用 Game 来演示模板模式的用法。

(1)、创建一个抽象类,将他的模板方法设置为 final

public abstract classGame {abstract voidinitialize();abstract voidstartPlay();abstract voidendPlay();//模板

public final voidplay(){//初始化游戏

initialize();//开始游戏

startPlay();//结束游戏

endPlay();

}

}

(2)、创建实体游戏类

public class Cricket extendsGame {

@OverridevoidendPlay() {

System.out.println("Cricket Game Finished!");

}

@Overridevoidinitialize() {

System.out.println("Cricket Game Initialized! Start playing.");

}

@OverridevoidstartPlay() {

System.out.println("Cricket Game Started. Enjoy the game!");

}

}

public class Football extendsGame {

@OverridevoidendPlay() {

System.out.println("Football Game Finished!");

}

@Overridevoidinitialize() {

System.out.println("Football Game Initialized! Start playing.");

}

@OverridevoidstartPlay() {

System.out.println("Football Game Started. Enjoy the game!");

}

}

(3)、使用 Game 的模板方法 play() 来演示游戏的定义方式。

public classTemplatePatternDemo {public static voidmain(String[] args) {

Game game= newCricket();

game.play();

System.out.println();

game= newFootball();

game.play();

}

}

(4)、演示结果

1 Cricket Game Initialized!Start playing.2 Cricket Game Started. Enjoy the game!

3 Cricket Game Finished!

4

5 Football Game Initialized!Start playing.6 Football Game Started. Enjoy the game!

7 Football Game Finished!

四、访问者模式(Visitor Pattern)

1、概念

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

2、简介

意图:主要将数据结构与数据操作分离。

主要解决:稳定的数据结构和易变的操作耦合问题。

何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

如何解决:在被访问的类里面加一个对外提供接待访问者的接口。

关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

应用实例:您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。

优点:

(1)、符合单一职责原则。

(2)、优秀的扩展性。

(3)、灵活性。

缺点:

(1)、具体元素对访问者公布细节,违反了迪米特原则。

(2)、具体元素变更比较困难。

(3)、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

使用场景:

(1)、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

(2)、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

3、实例

我们将创建一个定义接受操作的 ComputerPart 接口。Keyboard、Mouse、Monitor 和 Computer 是实现了 ComputerPart 接口的实体类。我们将定义另一个接口 ComputerPartVisitor,它定义了访问者类的操作。Computer 使用实体访问者来执行相应的动作。演示类 VisitorPatternDemo,我们的演示类使用 Computer、ComputerPartVisitor 类来演示访问者模式的用法。

(1)、定义一个表示元素的接口

public interfaceComputerPart {public voidaccept(ComputerPartVisitor computerPartVisitor);

}

(2)、扩展不同访问的实体类

public class Keyboard implementsComputerPart {

@Overridepublic voidaccept(ComputerPartVisitor computerPartVisitor) {

computerPartVisitor.visit(this);

}

}

public class Monitor implementsComputerPart {

@Overridepublic voidaccept(ComputerPartVisitor computerPartVisitor) {

computerPartVisitor.visit(this);

}

}

public class Mouse implementsComputerPart {

@Overridepublic voidaccept(ComputerPartVisitor computerPartVisitor) {

computerPartVisitor.visit(this);

}

}

public class Computer implementsComputerPart {

ComputerPart[] parts;publicComputer(){

parts= new ComputerPart[] {new Mouse(), new Keyboard(), newMonitor()};

}

@Overridepublic voidaccept(ComputerPartVisitor computerPartVisitor) {for (int i = 0; i < parts.length; i++) {

parts[i].accept(computerPartVisitor);

}

computerPartVisitor.visit(this);

}

}

(3)、定义一个表示访问者的接口

public interfaceComputerPartVisitor {public voidvisit(Computer computer);public voidvisit(Mouse mouse);public voidvisit(Keyboard keyboard);public voidvisit(Monitor monitor);

}

(4)、创建实现了上述类的实体访问者

public class ComputerPartDisplayVisitor implementsComputerPartVisitor {

@Overridepublic voidvisit(Computer computer) {

System.out.println("Displaying Computer.");

}

@Overridepublic voidvisit(Mouse mouse) {

System.out.println("Displaying Mouse.");

}

@Overridepublic voidvisit(Keyboard keyboard) {

System.out.println("Displaying Keyboard.");

}

@Overridepublic voidvisit(Monitor monitor) {

System.out.println("Displaying Monitor.");

}

}

(5)、使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。

public classVisitorPatternDemo {public static voidmain(String[] args) {

ComputerPart computer= newComputer();

computer.accept(newComputerPartDisplayVisitor());

}

}

(6)、演示结果

1 Displaying Mouse.2 Displaying Keyboard.3 Displaying Monitor.4 Displaying Computer.

行为型模式的介绍就到这里了,如有误,还请各位大佬指正;

java real football_Java学习--设计模式之行为型模式(三)相关推荐

  1. Java经典23种设计模式之行为型模式(三)

    本文接着介绍11种行为型模式里的备忘录模式.观察者模式.状态模式. 一.备忘录模式 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以将该对象恢复到原先保存的状 ...

  2. Java学习--设计模式之创建型模式

    一.简介 创建型模式:这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象.这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活.创建型模式包括:工 ...

  3. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

  4. 设计模式_行为型模式学习

    我们知道,创建型设计模式主要解决"对象的创建"问题,结构型设计模式主要解决"类或对象的组合或组装"问题,那行为型设计模式主要解决的就是"类或对象之间的 ...

  5. 备战面试日记(3.2) - (设计模式.23种设计模式之创建型模式)

    本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.6 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文章 ...

  6. 备战面试日记(3.4) - (设计模式.23种设计模式之行为型模式)

    本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.12 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文 ...

  7. 设计模式之创建型模式(工厂、原型、建造者)

    文章目录 创建型模式 2.1 工厂设计模式 2.1.1 简单工厂模式 2.1.2 工厂方法模式 2.1.3 抽象工厂 2.1.4 工厂模式总结 2.1.5 Spring中的工厂模式 2.1.6 工作中 ...

  8. Java最全的设计模式之结构型模式

    这篇接着上篇,结构型模式包含了七种,没有看过上篇的可以点击超链接 Java设计模式之创建型模式 Java设计模式之创建型模式 9.适配器模式 9.1结构型模式 9.2适配器模式的定义 9.3适配器模式 ...

  9. 设计模式之行为型模式(7种)

    目录 一.模版方法模式(template ) 概念 模式中的角色 模板模式UML类图 案例 使用前 使用后 钩子函数应用场景 注意事项和细节 应用 优点 模板方法模式与开闭原则 二.命令模式 概念: ...

最新文章

  1. VS中解决LIBCMTD.lib和uafxcwd.lib冲突(uafxcw.lib LIBCMT.lib冲突)
  2. java8 stream中的惰性求值
  3. git pull 提示错误,Your local changes to the following files would be overwritten by merge
  4. 卡图星小机器人怎么过_安徽交通广播90.8专题报道:阿尔法大蛋机器人,家里的新成员!...
  5. delete table 和 truncate table
  6. 活动目录的介绍:深入浅出Active Directory系列(一)
  7. 阅读笔记——《R数据可视化手册》肖楠等;主要ggplot2
  8. linux 运行菜刀,Linux部署常用命令
  9. NetApp收购Data Domain 当上冤大头?
  10. maven 打包命令
  11. VMware中的虚拟机开启VT,支持KVM
  12. 外贸客户来源的渠道有哪些?
  13. AFN TTP状态 412 - 前置条件失败
  14. 数据结构和算法 第六天内核链表是链表的终结者
  15. MKMapView用法
  16. 入小学教材、主流编程语言增长最快…… Python 的 2017 回顾
  17. 玩股票的人都是接盘侠
  18. ad hoc java_Java并发编程--线程封闭(Ad-hoc封闭 栈封闭 ThreadLocal)
  19. 家族关系查询系统程序设计算法思路_数据结构课程设计--
  20. java 解析Json对象(嵌套json数组)

热门文章

  1. 阿里云PyODPS 0.7.18发布,针对聚合函数进行优化同时新增对Python 3.7支持
  2. 自定义ProgressBar
  3. ruby动态new对象
  4. 《JavaScript高效图形编程(修订版)》——6.10 用画布sprites取代DHTMLsprite
  5. shiro的简单使用
  6. openAL在mac下播放音源结束时判断处理
  7. Android应用自动更新功能实现使用AsyncTask!
  8. 在EditText里插入图片,基于图库选择之后
  9. linux内核打开prntk,操作系统实验一向Linux内核增加一个系统调用.docx
  10. Java实现算法导论中快速傅里叶变换FFT递归算法