一、设计模式分类
Java的设计模式共包括23种,从设计目的(即要解决的问题)进行划分,分为创建型模式、结构型模式与行为型模式三类:
- 创建型模式:即实现怎样创建对象,将对象的创建与使用分离。包括单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式。
- 结构型模式:将类或对象按某种布局组成更大的结构,包括代理、适配器、桥接、装饰、外观、享元、组合 7 种结构型模式。
- 行为型模式:将类或对象之间通过职责分配协作完成单个对象都无法单独完成的任务。包括模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式
二、面向对象设计原则
为提高软件可复用性与可维护性,增强软件的可扩展性和灵活性,设计师提出了7条设计原则用于指导开发者设计程序:
1.开闭原则
当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。
2.里氏替换原则
子类可以扩展父类的功能,但不能改变父类原有的功能。即子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
3.依赖倒置原则
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。即要面向接口编程,不要面向实现编程。通过要面向接口的编程来降低类间的耦合性。
对于实际编程而言,依赖倒置原则主要需注意以下4点:
- 每个类尽量提供接口或抽象类,或者两者都具备。
- 变量的声明类型尽量是接口或者是抽象类。
- 任何类都不应该从具体类派生。
- 使用继承时尽量遵循里氏替换原则。
以买房为例阐述依赖倒置原则:购房者要购置房产,则涉及“购房者”与“房屋”两个类
public class Customer {
public void buyHouse(Villa villa){
System.out.println(villa.sell());
}
}
如果按上述方式将参数定义为具体实现类,则更换房屋类型时即需要更改函数定义:
public class Customer {
public void buyHouse(Department department){
System.out.println(department.sell());
}
}
即更换房屋类型,就要修改代码,这明显违背了开闭原则。存在以上缺点的原因是:顾客类设计时同具体的房屋类绑定,违背了依赖倒置原则。应定义房屋的共同接口 House,顾客类面向该接口编程,其代码修改如下:
public class Test
{
public static void main(String[] args)
{
Customer jl=new Customer();
System.out.println("顾客购买:");
jl.buyHouse(new Villa());
jl.buyHouse(new Department());
}
}
interface House
{
public String sell(); //卖
}
//别墅
class Villa implements House
{
public String sell()
{
return "别墅";
}
}
//公寓
class Department implements House
{
public String sell()
{
return "公寓";
}
}
//顾客
class Customer
{
public void buyHouse(House house)
{
//购房
System.out.println(house.sell());
}
}
4.单一职责原则
该原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
5.接口隔离原则
接口隔离原则要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。
要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
6.迪米特法则
又称最少知识法则,迪米特法则的定义是:只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
7.合成复用原则
要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
合成复用原则是通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。
以汽车分类为例:
汽车按“动力源”划分可分为汽油汽车、电动汽车等;按“颜色”划分可分为白色汽车、黑色汽车和红色汽车等。如果同时考虑这两种分类,其组合就很多。以下是按照能源与颜色进行分类的结构示意图:
上图结构的继承关系使得子类臃肿繁多,且增加新的“动力源”或者增加新的“颜色”都要修改源代码。