一:设计模式
- 概念:设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
- 目的:为了代码可重用性,让代码更容易被他人理解、保证代码可靠性。设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
二:设计原则
设计模式就是因为实现了设计原则(面向对象),从而达到了代码复用,增加可维护性的目的。
- 开闭原则(Open Close Principle)
对扩展开发,对修改关闭
在程序需要进行扩展的时候,不能去修改原有的代码 - 里氏替换原则(Liskov Substitution Principle)
任何基类可以出现的地方,子类一定可以出现
里氏替换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化。而基类于子类的继承关系就是抽象化的具体实现。
- 依赖倒置原则(Dependence Inversion Principle)
面向接口编程,依赖于抽象/接口,而不依赖于具体实现
这个是开闭原则的基础
- 接口隔离原则(Interface Segregation Principle)
使用多个接口比使用单一接口要好,降低代码的耦合度 - 迪米特法则(最少知道原则)(Demeter Principle)
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。 - 单一职责原则(Single Responsibility Principle)
一个类只做一件事
三:设计模式的分类
总体来说设计模式分为三大类
- 创建型模式,共五种:单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。
- 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为模式,共十一钟:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问模式、中介者模式、解释器模式。
本章重点-----创建型模式之工厂模式
1. 定义:
工厂方法模式(Factory Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂模式使一个类的实例化延迟到其子类。
类图:
抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义;Creator为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。
2. 示例
- 比如组装汽车:发动机、车轮、地盘
class Engine {
public void getStyle(){
System.out.println("这是汽车的发动机");
}
}
class Underpan {
public void getStyle(){
System.out.println("这是汽车的底盘");
}
}
class Wheel {
public void getStyle(){
System.out.println("这是汽车的轮胎");
}
}
public class Client {
public static void main(String[] args) {
Engine engine = new Engine();
Underpan underpan = new Underpan();
Wheel wheel = new Wheel();
ICar car = new Car(underpan, wheel, engine);
car.show();
}
}
从上面的代码中我们可以看到,调用者为了组装汽车还需要另外实例化发动机、底盘和轮胎,
而且这些汽车的组件是与调用者无关的,严重违反了迪米特法则,耦合度太高。并且非常不利于扩展。调用者组装其他车型,还需调用另外组件的来组装,所以,这里我们使用工厂模式,让调用者根本不用知道怎样组装产品,直接获取产品实例
interface IFactory {
public ICar createCar();
}
class Factory implements IFactory {
public ICar createCar() {
Engine engine = new Engine();
Underpan underpan = new Underpan();
Wheel wheel = new Wheel();
ICar car = new Car(underpan, wheel, engine);
return car;
}
private Factory(){}
}
public class Client {
public static void main(String[] args) {
IFactory factory = new Factory();
ICar car = factory.createCar();
car.show();
}
}
由此,我们可以看到,使用工厂模式后,调用端的耦合度大大降低了,并且对于工厂来说,如果想组装其他车辆,只需要再实现一个工厂就可以了,无论使灵活性还是稳定性都得到了极大提高
3.工厂模式的应用
1. 优点:
- 工厂模式具有:良好的封装性,代码结构清晰。
一个对象创建是有条件约束的,如一个调用者需要一个具体的产品对象,只需要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,降低模块的耦合。 - 工厂模式的扩展性非常优秀。在增加产品类的情况下,只需要适当地修改具体地工厂类或扩展一个工厂类,就可以完成 “拥抱变化”.例如在我们的例子中,我们需要增加另外的车型,只需要在实现一个工厂类,就可以完成系统扩展。
- 符合迪米特法则。产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。如:线程池的创建(Executors)
- 符合依赖倒置原则。只依赖产品的抽象类/接口。
2. 使用场景
首先,工厂模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以使用,但是需要慎重地考虑是否要增加一个工厂类进行管理,增加代码地复杂度。
其次,需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
例如:需要设计一个连接邮件服务器的框架,有三种网络协议可供选择:POP3、IMAP、HTTP,我们就可以把这三种连接方法作为产品类,定义一个接口IConnectMail,然后定义对有邮件的操作方法,用不同的方法实现三个具体的产品类(也就是连接方式)再定义一个工厂方法,按照不同的传入条件,选择不同的连接方式。如此设计,就可以做到完美的扩展,如某些邮件服务器通过了WebService接口,很好,我们只需要增加一个产品类就可以了。