Java 设计模式 -- 示例指南
设计模式在软件开发者中非常受欢迎的。每个设计模式都是对常见软件问题的通用的描述解决方案。
我们使用设计模式的好处有:
- 1.设计模式已经对于一个重复出现的问题进行了定义并且提供了工业标准的解决方案,因为如果我们合理的使用设计模式就可以节省很多时间。
- 2.使用设计模式提供的复用性可以产生更加稳健和高可控的代码。它可以帮助减少软件产品的总的花费。
- 3.因为设计模式已经被定义好了,所以它让我们的代码更加容易去理解和调试。它可以提供更加快速的开发并且使团队中的乘以更容易的理解。
Java设计模式被分成了三类-创建型、结构型和行为型的设计模式。这种划分就是所有我写的设计模式的一个目录索引。
- 创建型设计模式
- 结构型设计模式
- 行为型设计模式
- 1.模板方法模式(Template Method Pattern)
- 2.中介者模式(Mediator Pattern)
- 3.责任链模式(Chain of Responsibility Pattern)
- 4.观察者模式(Observer Pattern)
- 5.策略模式(Strategy Pattern)
- 6.命令模式(Command Pattern)
- 7.状态模式(State Pattern)
- 8.访问者模式(Visitor Pattern)
- 9.解释器模式(Interpreter Pattern)
- 10.迭代器模式(Iterator Pattern)
- 11.备忘录模式(Memento Pattern)
创建型设计模式
创建型设计模式可以使用规范方案中最合适的方式来实体化一个对象。
1.单例模式(Singleton Pattern)
单例模式约束了一个类的实例化并且确保在JVM中只会存在一个类的实例。这个看起来非常简单的设计模式但是在实现起来的时候会带来很多的实现问题。单例模式的实现在开发中中通常是一个有争议性的话题。看下 Singleton Design Pattern文章来了解到实现单例模式的不同方法还有每个方法的优点和缺点。
2.工厂模式(Factory Pattern)
当我们有一个父类而且它有多个子类子,我们需要还有依赖输入返回一个子类,那我们就需要使用工厂设计模式了。这个方法将一个实例化类的职责从客户端程序拿到了工厂类中。我们可以在工厂类中应用单例模式或者将工厂方法设置为static类型的。看下Factory Design Pattern的例子了解工厂模式的优势。
3.抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式和工厂模式类似,它是工厂的工厂。如果你对工厂摸是熟悉的话那么你会注意到我们有一个根据给定的输入返回不同的子类,工厂类可以使用if-else或者switch语句来达到这个目的。
在抽象工厂模式中,我们不在使用if-else快而且对于每一个子类都有一个工厂类,并且有一个根据输入的工厂类返回子类的抽象工厂类。看 Abstract Factory Pattern 来了解如何用代码实现这个模式。
4.建造者模式(Builder Pattern)
这个模式被引入是为了解决一个对象有很多属性的时候用工厂和抽象工厂设计模式的一些问题。建造者模式通过提供一个一步步构建的方式来解决含有大量可选参数和不一致状态的问题,并且提供了可以真正返回最终对象的方法。看下文章 Builder Pattern来看下实例和在JDK中使用的相关类。
5.原型模式(Prototype Pattern)
原型模式被用在当一个对象的创建是有大量的代价而且需要大量的时间和资源并且你有一个已经存在的相似的对象的时候。所以这个模式提供了将原始对象复制到新的对象的机制,而且你可以根据你的需要修改它。这个模式使用了java克隆来复制对象。
原型设计模式允许你复制的对象提供可以复制的功能。它不应该是通过其他类来完成的。但是不管怎么说是否使用浅拷贝或者是深拷贝一个对象的属性取决于需求和设计。看文章来 Prototype Pattern看简单的示例。
结构型设计模式
结构型设计模式提供了创建类结构的不同方式,比如说,使用继承和组合的方式从小的对象来创建打的对象。
1.适配器模式(Adapter Pattern)
适配器设计模式时一个结构型的设计模式,它用于将两个没有关系的接口可以在一起起作用。将这些无关的接口组合在一起的对象就是一个适配器。拿生活中一个实际的场景,我们可以把手机充电器当成是一个适配器因为手机电池需要使用3V的电,但是一般情况下电插板只是产生120V或者240V的电。所以手机充电器就是在手机充电板和正常充电板充当一个适配器的。看下文章 Adapter Pattern 来看下它是如何在Java中应用的。
2.组合模式(Composite Pattern)
组合模式是一种结构型设计模式并且被用在当我们必须要表示一个整体和部分的层次关系时。当我们需要一种在结构中的所有对象都需要被相同的方式被处理的方式来创建一个结构时,我们就可以使用组合设计模式。
让我们拿生活中的实例来说明--一个图是由比如圆和直线、角这些对象组成的结构,而且我们当我们需要用颜色来填充的时候,需要把相同的对象使用相同的颜色。那么画是由不同的部分组成的而且他们都有一些相似的操作。看文章Composite Pattern 来看组合模式的不同组件以及代码例子。
3.代理模式(Proxy Pattern)
代理模式的目的是为其他对象提供一个代理或者占位来控制访问。这个定义是很清晰的而且代理模式在我们想去提供对一个函数的访问控制的时候可以被使用。
也就是说我们在系统中有些可以运行命令的类。现在如果我们要使用它,这个是OK的,但是如果我们如果我们把程序交给客户端应用的话,因为客户端可能去运行一些命令去删除或者修改你不想让它删除的设置或者系统文件,那么这样就会产生问题。看下文章 Proxy Pattern 来看下具体的实现例子。
4.享元模式(Flyweight Pattern)
享元设计模式被用在当我们需要去创建一个类的大量对象的时候。因为每一个对象每一个对象都会消耗内存空间,这个对于比如手机或者嵌入式系统是非常不好的。享元设计模式通过共享对象的方式来减少内存的加载。字符串池的实现就是享元设计模式的最好实现例子。看文章Flyweight Pattern来了解简单的实现过程。
5.外观模式(Facade Pattern)
外观模式被用在帮助客户端程序和系统进行更加容易的交互。假设我么有一个接口集合的应用程序去使用MYSQL\Oracle数据库并且生成不同类型的报告,比如HTML报告,PDF报告等等。所以我们为了处理不同类型的数据库我们需要不同的接口集。现在一个客户端应用能够使用这些接口去获取需要的数据库连接并且生成报告。但是当复杂性增加或者接口行为的名词让我们疑惑的时候,客户端程序会是难去维护的。所以我们就可以使用外观模式并且在存在接口的顶部提供一个封装接口来帮助客户端程序。看文章Facade Pattern来看下详细的实现。
6.桥接模式(Bridge Pattern)
当我们在你接口和实现中有接口层次的时候,桥接模式就可以用于将接口从实现中解耦并且从客户端程序中隐藏详细的实现。像适配器模式一样,它是一个结构型设计模式。
桥接模式的实现遵从了多用组合而不是继承的原则。看文章Bridge Pattern的详细实现。
7.装饰器模式(Decorator Pattern)
装饰器模式用于修改在运行时对象的功能的。与此同时相同类的其他实例将不会受到影响,所以每个独立的对象拥有修改后的行为。装饰器模式一个结构型设计模式的一种,而且使用使用抽象类或者接口的组合方式来实现的。
我们使用继承或者组合去扩展一个对象的行为但是这个在编译的时候就已经完成了,并且这个可以应用到所有的类的实例上。我们不能在运行的时候添加新的功能 或者移除任何已经存在的行为--这时候我们就需要使用装饰器模式了。看文章Decorator Pattern来看下详细的实现。
行为型设计模式
行为型设计模式为在对象之间进行更好的交互以及如何提供不用耦合和灵活的扩展提供了解决方案。
1.模板方法模式(Template Method Pattern)
模板方法是一个行为型设计模式而且它用于创建一个方法stub而且推迟了一些的实现步骤到子类中。模板方法定义了运行一个算法的步骤而且它能够提供有可能是所有的或者部分子类的公共的默认实现。
假设我们想去使用一个算法来建造一个房子。为了建造房子需要有的步骤包括-打地基、打柱子、垒墙并且安窗户。很重的一点就是我们不嗯呢该改变这些顺序因为我们不在打地基之前就安窗户。在这个实力中我们能够创建一个可以使用不同方法构建屋子的模板方法。看文章Template Method Pattern来看具体的实现和代码。
2.中介者模式(Mediator Pattern)
中介者设计模式用于提供一个在系统中的不同对象之间中间的交流媒介。中介者设计模式在一个有很多对象需要彼此交互的企业级应用中是非常有用的。如果对象直接彼此交互,那么系统就会紧紧的耦合在一起从而使维护花费更大而且不利于灵活的进行扩展。中介者模式的目的是提供了对象之间的联系并且帮助对象之间的解耦。
空中交通指挥员就是一个中介者模式使用很棒的例子,因为机场控制室充当了各个航班的联系的中介者。中介者在对象之间充当路由器并且它可以有自己的逻辑来提供交流联系的方式。看文章 Mediator Pattern来代码的具体实现。
3.责任链模式(Chain of Responsibility Pattern)
责任链模式用于在软件设计中有来自客户端的请求需要传递给一串对象来处理的场景中解耦的。在链中的对象将会决定谁将处理这个情况并且这个请求是否需要传递给链中的下一个对象。
我们清楚我们在一个try-cathc代码块中可以有多个catch块。这里每一个catch块都是一种形式的处理器去处理特殊的异常。所以当在try中出现任何异常的时候,它会传递给第一个catch块。如果catch块没办法处理它,它会将情况传递给下个对象。即使最后一个catch块没办法处理它,那么异常将会抛出到链的外面到调用它的程序。
ATM分发机逻辑就是使用了 Chain of Responsibility Pattern的实现,看下链接。
4.观察者模式(Observer Pattern)
观察者模式在你对一个对象的状态感兴趣并且希望在任何时候发生改变的时候都能够得到通知的场景下是很有用的。在观察者模式中,观察其他对象的状态的对象被称为Observer,而被观察的对象被称为Subject。
Java通过java.util.Observable类和java.util.Observer接口提供了内置的观察者模式的实现。的但是因为这个实现非常的简单而且大部分的时候我们不想通过扩展一个类来实现观察者模式因为java不提供类的多继承,所以它被使用的不广泛。
Java消息服务(JMS)使用中介者模式中在介者模式中一块来允许应用来订阅和发布数据到其他的应用中。看文章Observer Pattern来具体的实现和示例程序。
5.策略模式(Strategy Pattern)
策略模式被用在当我们对于一个指定的任务有多个算法的时候而且客户端在运行时决定实际的使用实现算法。
策略模式也被熟知是Policy Pattern。我们定义多个算法而且让客户端传递需要使用的算法作为参数。诠释最好的例子就是 Collections.sort() 方法的Comparator 参数。基于不同的比较器接口的实现,对象就会使用不同的方法来进行排序。
看文章Strategy Pattern 来看具体的实现和实例程序。
6.命令模式(Command Pattern)
命令模式用于在请求应答模型中解耦和的。在命令模式中,一个请求被你发送给调用者(invoker)而且invoker把它传递给封装好的command对象。command对象将请求传递给合适的接收者(receiver)来进行处理。
可以这样解释,我们想去为一个文件系统一个能够打开、写和关闭的方法而且它能够支持例如windows和Unix等多个操作系统。为了系统我们的文件系统,首先我们需要创建最后实际工作 的receiver类。因为我们是以java接口的形式来编码,我们需要有FileSystemReceiver 接口和它的针对不同的OS的具体实现类,例如 Windows, Unix, Solaris 等等。看文章 Command Pattern的具体实现以及代码实例。
7.状态模式(State Pattern)
状态模式用于当一个对象需要基于它的内部状态来改变他的行为的时候。
如果我们必须必须根据他的状态来它的行为时,我们可以在对象的内部设置一个状态变量然后使用if-else条件块来表示基于不同状态的行为。状态模式用于提供一个系统的低耦合的方法来通过上下文和状态继承来实现的。看文章State Pattern来看具体的详细实现以及代码实例。
8.访问者模式(Visitor Pattern)
访问者模式被用于当我们必须在一组相似的对象中进行一个操作的时候。使用访问者模式,我们可以讲操作逻辑从一个对象移到另外一个类中。
例如,想象一个超市的手推车我们可以在里面添加不同的东西,当我们点击出账按钮时,它就会计算需要付钱的总量。现在我们有在具体的计算逻辑或者我们可以把这个逻辑使用观察者模式移到其他的类中。看文章 Visitor Pattern来看看那具体的实现。
9.解释器模式(Interpreter Pattern)
解释器模式用于对于一个语言定义语法的表示并且提供处理这种语法的解释器。
这个模式的最好的例子就是java编译器来将java源代码解释成JVM能够理解的字节码。Google的翻译器就是解释器模式的例子,以任何语言的输入我们都可以得到被翻译成的另外语言。看文章 Interpreter Pattern来看下例子。
10.迭代器模式(Iterator Pattern)
迭代器模式是一种行为型模式,它用于提供一个标准的方式去遍历一组对象。迭代器模式中带Java集合中得到了大范围的应用。
迭代器模式不仅仅只是遍历一个集合,我们可以根据我们的需求提供不同类型的迭代器。迭代器模式隐藏了遍历集合的具体实现,客户端程序只需要使用迭代器方法。看文章 Iterator Pattern来看下具体的实现。
11.备忘录模式(Memento Pattern)
备忘录设计模式用于当我们想去保存一个对象的状态然后在后来恢复这个状态的情况下。备忘录模式通过首先保存这个对象的状态数据但是不能通过外部对象来访问,从而保护了保存数据的完整性。
备忘录模式时通过两个对象来实现的– Originator 和 Caretaker。Originator就是那个状态需要保存和恢复的对象,它使用了内部类来保存对象的状态。这个内部类就是被称为备忘录而且他是私有的,所有并不能通过其他对象来访问它。看文章 Memento Pattern来看下程序例子和详细的实现。
这就是java 中所有的不同的设计模式,这篇文章提供了更容易浏览所有模式的目录索引。