郑苗
摘要:软件开发中,最重要的不是后期的编码,而是前期的设计,甚至可以毫不夸张地说,一个软件的好坏就取决于设计,因为前期的设计会直接影响后期的开发以及维护。从中,我们就可以知道设计是多么重要,这样一来,理解并学习设计模式就显得很有必要了。而在目前市面上出现的多种编程语言中,Java的热度是最高的。因此该文将通过Java来阐述对目前较流行的几种设计模式的理解与实现。
关键词:软件开发;实现;Java;设计模式
中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2017)32-0115-02
1 概述
总体而言,设计模式(Design pattern)是一种设计经验的总结。它是经过前人理解、深挖、设计、广泛使用之后,总结出来的。其目的是为了让代码拥有更强的可读性、更容易被开发者理解、可被重复利用、更可靠。毫无夸张地说,对于开发者以及系统本身,设计模式都是很有利的,设计模式,可以使编程更加地充满乐趣,使代码更加地规范。如果把一个系统比作海洋中航行的巨轮的话,那么设计模式就是这艘巨轮中的钢架结构设计,合理地使用设计模式,可以使这艘巨轮更加牢固,能够抵抗住各种考验,解决面临的问题,也有利于后期的升级改造,会让它走得更稳更远。
2 设计模式的分类
2.1 创建型模式
原型模式、建造者模式、工厂方法模式、单例模式、抽象工厂模式。
2.2 结构型模式
装饰器模式、适配器模式、外观模式、代理模式、享元模式、组合模式、桥接模式。
2.3 行为型模式
解释器模式、策略模式、模版方法模式、观察者模式、责任链模式、命令模式、迭代子模式、备忘录模式、状态模式、中介者模式、访问者模式。
3 设计模式的六大原则
3.1 开闭原则
什么叫开闭原则呢?其实意思就是对修改是关闭的,但是对扩展是开放的。当我们的系统在面临升级,需要对它做一些扩展,这个时候,对于之前的那些代码,我们最好是不要去做修改。用比较专业的术语来说就是:想要让我们的系统更好地升级和维护,拥有更好的扩展性,需要我们去使用抽象类和接口。
3.2 里氏代换原则
什么叫里氏代换原则呢?面向对象程序设计对于开发者而言,应该是耳熟能详的,而这个里氏代换原则就是面向对象程序设计的基本原则之一。简单来说,里氏代换原则是指,子类可以出现在任何基类可以出现的地方。作为继承复用的基础,里氏代换原则中,基类被复用有一个前提,那就是软件单位的功能不会因为子类替换掉基类的而受到影响,从而,子类也可以基于基类增加新的功能。其实这个原则也可以说是对上面“开闭原则”的补充。“开闭原则”的实现,很重要的一步就是做抽象化处理。而子类与基类之间的继承关系也具体实现了抽象化,因此,换言之,里氏代换原则规范了实现抽象化的具体步骤。
3.3 依赖倒转原则
这个原则是作为开闭原则的基础,它的意思是指,当我们面向接口编程的时候,我们是需要依赖抽象,但是不依赖具体的。
3.4 接口隔离原则
接口隔离原则是指:使用单个接口不会比使用多个隔离的接口要好。就是松耦合的意思,我们从这儿不难看出,设计模式其实就是作为软件的设计思想,它是从软件架构着手的,目的是为了维护容易和升级。
3.5 迪米特法则
这个也叫做最少知道原则,为什么叫这个呢? 意思是:实体之间需要尽可能少的相互作用,这样就可以使系统各个功能模块看起来是相对独立的,也能便于维护。
3.6 合成复用原则
原则是不使用继承,尽量使用合成/聚合的方式。
4 设计模式详细实现
4.1 代理模式(Proxy)
顾名思义,在该种模式下,会有一种代理类的产生,通过该代理类,我们可以拥有原对象的一些功能,比如我们在买火车票的时候有时会去一些代售点而不是直接去火车站,这里的代售点就是代理的意思。
根据上文的阐述,代理模式就比较容易理解了,我们看下代码实现:
interface Station {
int saleTicket(); }
class BeijingStation implements Station {
@Override
int saleTicket() {
System.out.println("beijing station can sale tickets!"); } }
class Xiecheng implements Station {
private Station station;
Xiecheng(){
super();
this.station = new Station(); }
@Override
int saleTicket() {
proxyBef();
station.saleTicket();
proxyAft(); }
int proxyAft() {
System.out.println(" proxyafter!"); }
int proxyBef() {
System.out.println("proxybefore !"); } }
代理模式有如下的應用场景:
当已有方法在使用时需要对之前的方法做一些改进时,有两种处理办法:endprint
1) 通过修改之前的方法来完成我们的需求。但是这样做的话,就违反了一个原则,那就是开闭原则。
2) 设置一个中间代理类,通过这个中间代理类来调用之前方法,并且,对这个类调用产生的结果做控制。
以上第2种方法就是很好地运用了代理模式,从中,我们不难看出,代理模式能够对功能做出更加清晰的划分,这对于后期维护是很有利的。
4.2 观察者模式( Observer)
这个模式讲的是类和类的关系,但是它跟继承是没有关系的。这种模式其实是比较容易理解的,它跟RSS订阅和邮件订阅的关系很像,比如,我们阅读wiki或博客时,RSS图标,我们会经常看到,放在这来讲就是,当你关注并订阅某篇文章,后续如果这篇文章有更新的话,它也会非常及时地通知到你。换言之:一个对象当它发生变化的时候,依赖该对象的其他对象是都会收到相应的通知的,而且也会做出相应的变化。对象与对象之间是一对多的关系。如图1所示。
这些类的作用,我来解释下:我们的主对象就是MySubject类,MySubject类有2个依赖于它的对象,就是Observer1和Observer2,当它发生变化的时候,依赖于它的Observer1和Observer2也必然会发生变化。而AbstractSubject类里则定义了对象列表,这些对象列表是需要被监控的,可以对其进行增加或删除被监控对象的修改,并且当主对象发生变化时,AbstractSubject会告警在其列表中存在的对象。具体代码如下:
定义Check接口:
interface Watch{
void change();
}
定义实现类:
class Watch1 implements Watch{
@Override
void change() {
System.out.println("watch1 gets!"); } }
class Watch2 implements Watch{
@Override
void change() {
System.out.println("watch2 gets!"); } }
实现类和AbstractSubject接口:
interface AbstractSubject{
/*观察者增加*/
void add(Watch watch);
/*观察者删除*/
void delete(Watch watch);
/*所有的观察者被通知*/
void tellWatchs();
void show();
}
abstract class ASubjectImpl implements AbstractSubject{
List
@Override
void add(Watch watch) {
list.add(watch); }
@Override
void del(Watch watch) {
list.remove(watch); }
@Override
void tellWatchs() {
for(int i=0;i Watch watch = list.get(i); watch.change();} } } class MySub extends ASubjectImpl { @Override void show() { System.out.println("change self!"); tellWatchs(); } } 观察者模式其实不难,只是有些抽象,不太容易整体理解,但是根据关系图以及参考我的代码,整理逻辑梳理一遍,这样就会比较容易理解了! 5 总结 设计模式的学习是一个长期的过程,需要几个阶段的学习,更要注重理论与实现的结合,大量地准确地将所学的设计模式运用到项目中去,充分发挥设计模式的作用,这样才能体会到它的奥妙之处。 参考文献: [1] 范伟.软件设计模式研究及应用[J]. 山东工业技术, 2015(20). [2] 罗兴荣.软件设计模式及其使用[J].数字技术与应用,2013(4). [3] 蒋继冬. 简单工厂模式在面向接口編程中的应用[J].电子技术与软件工程,2013(20). [4] 刘耀钦.单例模式及其扩展在Web开发中的应用分析[J].计算机系统应用,2014(5). [5] 杜增毅. 浅谈主要的Java设计模式[J].电脑迷,2017(4).