设计模式之创建型模式
设计模式分为三大类:
(1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
(2)结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
(3)行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
简单工厂模式(SimpleFactoryPattern)--将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。
优点:
- 将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦;
- 把初始化实例时的工作放到工厂里进行,使代码更容易维护。 更符合面向对象的原则 & 面向接口编程,而不是面向实现编程。
缺点:
- 工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
- 违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。
- 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。
- 更符合开-闭原则(新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可)
- 符合单一职责原则(每个具体工厂类只负责创建对应的产品)
- 不使用静态工厂方法,可以形成基于继承的等级结构。
- 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
抽象工厂模式(Abstract Factory)--允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。
抽象工厂模式解决的问题是工厂方法模式的缺点:每个工厂只能创建一类产品
优点:
- 降低耦合(抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展)
- 更符合开-闭原则(新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可)
- 符合单一职责原则
缺点:
- 抽象工厂模式很难支持新种类产品的变化
这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。
单例模式(Singleton)--保证1个类只有1个对象,降低对象之间的耦合度
优点:
- 提供了对唯一实例的受控访问;
- 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能;
缺点:
- 单例类的职责过重,里面的代码可能会过于复杂,在一定程度上违背了“单一职责原则”。
- 如果实例化的对象长时间不被利用,会被系统认为是垃圾而被回收,这将导致对象状态的丢失。
建造者模式(Builder Pattern)--将一个复杂对象的构建与它的表示分离
优点:
- 易于解耦
将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。
- 易于精确控制对象的创建
将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
- 易于拓展
增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
Prototype原型模式--用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
优点:
- 原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好很多,尤其是构造函数比较复杂,并且在循环体中生产出大量的对象时,用原型模式效率很高。
- 原型模式-在拷贝时构造函数是不执行的