一、什么是设计模式
设计模式是指在软件开发中,经过验证的,用以解决在特定环境下、重复出现的,特定问题的解决方案。
在描述单个设计模式时,设计模式通常由以下部分组成。
模式名称
环境和问题:描述在什么场景下,出现什么样的特定的问题。
解决方案:描述如何解决这个问题。
效果:描述模式应用的效果,以及可能带来的问题,或者使用中需要权衡的问题。
设计模式的分类
创建型模式:抽象了对象实例化的过程,用来帮助创建对象的实例。
结构型模式:描述如何组合类和对象以获得更大的结构。
行为型模式:描述算法和对象间职责的分配。
二、常见的面向对象设计的原则
1、单一职责原则SRP(Single Responsibility Principle)
单一职责,指的是,一个类应该仅有一个引起它变化的原因。
这里所说的原因就是所谓的“职责”,如果一个类有多个引起它变化的原因,那么也就意味着这个类有多个职责,再进一步说,就是把多个职责耦合到一起了。
这会造成职责的相互影响,可能一个职责的变化,会影响到其他职责的实现,甚至引起其他职责随着变化,这种设计是脆弱的。
2、开放-关闭原则OCP(Open-Close Principle)
所谓开闭原则,是指一个类应该对扩展开放,对修改关闭,它是设计中一个非常核心的原则。
开闭原则要求的是,类的行为是可以扩展的,而且是在不修改已有代码的情况下进行扩展,也不必改动已有的源代码或者二进制代码。
实现开闭原则的关键是合理地抽象、分离出变化和不变化的部分,为变化的部分预留下可扩展的方式,比如,钩子方法或是动态组合对象等。
3、里氏替换原则LSP(Liskov Substitution Priciple)
所谓的里氏替换原则,指的是,子类型必须能够替换掉它们的父类型。这是一种多态的使用情况,它可以避免在多态的应用中,出现某些隐蔽的错误。
从另外一个角度来说,里氏替换原则是实现开闭的主要原则之一。开闭原则要求对扩展开放,扩展的一个手段就是使用继承;而里氏替换原则是保证子类能够正确替换父类型,只有能正确替换,才能实现扩展,否则扩展了也会出现错误。
4、依赖倒置原则DIP(Dependence Inversion Principle)
所谓依赖倒置原则,指的是,要依赖于抽象,不要依赖于具体类。要做到依赖倒置,典型的应该做到:
高层模块不应该依赖于底层模块,二者都应该依赖于抽象。
抽象类不应该依赖于具体实现,具体实现应该依赖于抽象类。
5、接口隔离原则ISP(Interface Segregation Principle)
所谓接口隔离原则,指的是,不应该强迫客户依赖于他们不用的方法。
这个原则用来处理那些比较“庞大”的接口,这种接口通常会声明较多的操作,涉及到很多的职责。客户在使用这样的接口的时候,通常会有很多他不需要的方法,这些方法对于客户来讲,就是一种接口污染,相当于强迫用户在一大堆的方法中去寻找他需要的方法。
因此这样的接口应该被隔离,应该按照不用客户的需求来分离成为针对客户的需求。这些接口中,只需要声明客户需要的操作声明,这样既方便了客户的使用,也可以避免误用接口而导致的错误。
分离接口的方式,除了直接进行代码分离之外,还可以用委托来分离接口。
6、最少知识原则LKP(Least Knowledge Principle)
所谓最少知识原则,指的是,只和自己的朋友谈话。
这个原则用来执导我们在设计系统的时候,应该尽量减少对象之间的交互,对象只和自己的朋友谈话,也就是只和自己的朋友交互,从而松散类之间的耦合。通过松散类之间的耦合来降低类之间的相互依赖,这样在修改系统的某一个部分的时候,就不会影响其他的部分,从而使系统具有更好的可维护性。
那么究竟哪些对象才能被的当作朋友呢?最少知识原则提提供了一些执导:
当前对象本身
通过方法的参数传递进来的对象
当前对象所创建的对象
当前对象的实例变量所引用的对象。
方法内所创建的或实例化的对象。
总之,最少知识原则要求我们的方法调用必须保持在一定的界限范围之内,尽量减少对象之间的依赖关系。
7、其他原则
面向接口编程
优先使用组合,而非继承
一个类需要的数据应该隐藏在类的内部;
类之间应该零耦合,或者只有传导耦合,换句话说,类之间要么没有关系,要么只使用另一个类的接口提供的操作;
在水平方向上尽可能统一地分布系统功能。
三、类图
1、类图的概念
类图是静态视图的图形表达方式,表示声明的静态模型元素,如类、类型和其内容,以及它们的相互关系。也就是说,类图是用来描述类及类与类之间关系的一种UML图。
2、类图的基本表达
类图的基本模型元素如下图所示:
-
类的名字
属性
操作
图1 类图的基本图示
属性定义的基本语法:
属性用来描述类所具有的特征。描述属性的语法格式为:
可见性属性名:类型名=初始值
其中属性名和类型名是必须要有的,其他部分是可选的。
对于可见性:+表示public,-表示private,#表示protected,没有符号则表示默认的可见性。
基本的示例如图:
-
User
-firstName:String
-lastName:String
+fullName:String
+age:int
图2 带属性的类图
操作的表示基本语法
基本语法格式如下:
可见性 操作名(参数列表):返回值类型
可见性和属性的描述方式是一样的,都是+表示public,-表示private,#表示protected,没有符号则表示默认的可见性。
参数列表由多个参数构成,用逗号分割参数,描述参数的语法格式为:
参数名:参数类型
为图2所示的类图添加一个方法:用户可以购买一定数量的某商品,如图3所示:
-
User
-firstName:String
-lastName:String
+fullName:String
+age:int
+buy(name:Product,num:int):void
图
3 带操作的类图
Java中static的表示
如果属性或者方法是static的,则在属性或方法定义的下面,添加一条下划线表示static的,如图4所示:
-
User
-age:int=20
-name:String
+run(speed:double,durableTime:double):void
图4 带静态属性和静态方法的类图
3、抽象类和接口
抽象类的表示是类名倾斜,抽象操作的表示是整条操作定义都倾斜,如图5所示:
-
AbstractClass
-name:String
+abstractMethod(s:int,b:String):String
+otherMethod():void
图5 抽象类
接口是一种特殊的抽象类,归根结底还是类,所以接口的表达基本语法和类是一样的,接口,定义示比如有一个创建用户和删除用户的例如图6所示
-
《interface》
UserService
+createUser(name:String,age:int):boolean
-delUser(name:String):boolean
图6 接口
四、类之间关系的图示(见文章:http://hi.baidu.com/yanft/item/61692b2d94b7450a42634ac1)
一般什么情况下需要自己实现classloader,例如tomcat,为什么要自己实现classloader?
怎样实现多继承?