一、工厂模式
只支持横向扩展,如增加新的产品。若需纵向扩展就会修改已有的产品代码。我们接口中心适配器就用的此模式,增加新xizang的车站client不会影响其他client,但是如果要增加接口,就会影响其他client。
二、抽象工厂模式
只支持纵向扩展,增加产品族容易,但是增加产品就会修改原有结构,和工厂模式相反。
三、单例模式
1、饿汉模式,空间换时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。
public class EagerSingleton { private static EagerSingleton instance = new EagerSingleton(); public static EagerSingleton getInstance() { return instance; } public static void main(String[] args) { System.out.println(EagerSingleton.getInstance()); } }
2、懒汉模式,时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间
public class LazySingleton { private static LazySingleton instance = null; public static synchronized LazySingleton getInstance() { if(instance == null) { instance = new LazySingleton(); } return instance; } public static void main(String[] args) { System.out.println(LazySingleton.getInstance()); } }
3、双检查模式
public class DoubleCheckSingleton { private volatile static DoubleCheckSingleton instance = null; public static DoubleCheckSingleton getInstance() { if(null == instance) { synchronized (DoubleCheckSingleton.class) { if(null == instance) { instance = new DoubleCheckSingleton(); } } } return instance; } }
4、Lazy initialization holder class模式,当getInstance方法第一次被调用的时候,它第一次读取SingletonHolder.instance,导致SingletonHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。
public class InnerSingleton { /** * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 * 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。 */ private static class SingletonHolder { /** * 静态初始化器,由JVM来保证线程安全 */ private static InnerSingleton instance = new InnerSingleton(); } public static InnerSingleton getInstance() { return SingletonHolder.instance; } }
5、枚举模式
public enum EnumSingleton { /** * 定义一个枚举的元素,它就代表了Singleton的一个实例。 */ uniqueInstance; /** * 单例可以有自己的操作 */ public void singletonOperation(){ //功能处理 } }
四、建造者模式
抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者 (ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的两种方法:一种是建造方法(buildPart1和 buildPart2),另一种是返还结构方法(retrieveResult)。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少 零件,就有多少相应的建造方法。
具体建造者(ConcreteBuilder)角色:担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:1.实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作。2.在建造过程完成后,提供产品的实例。
导演者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。应当指出的是,导演者角色并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者角色。
产品(Product)角色:产品便是建造中的复杂对象。一般来说,一个系统中会有多于一个的产品类,而且这些产品类并不一定有共同的接口,而完全可以是不相关联的。
五、原型模式
创建对象使用,避免过多的new,且需要设置大量属性情况下使用。
浅克隆:只负责克隆按值传递的数据(比如基本数据类型、String类型),而不复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。
深克隆:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据
六、适配器模式
适配器模式包括类适配器模式、对象适配器、缺省适配器模式
1、类适配器模式
2、对象适配器
3、缺省适配器
定义一个空格抽象类,去实现接口,抽象类子类则可以选择性的实现接口,而不用全部实现所有接口。这种模式比较平庸和浪费,因为定义了一个空的抽象类。
类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。
对于类适配器,由于适配器直接继承了Adaptee,使得适配器不能和Adaptee的子类一起工作,因为继承是静态的关系,当适配器继承了Adaptee后,就不可能再去处理 Adaptee的子类了。
对于对象适配器,一个适配器可以把多种不同的源适配到同一个目标。换言之,同一个适配器可以把源类和它的子类都适配到目标接口。因为对象适配器采用的是对象组合的关系,只要对象类型正确,是不是子类都无所谓。
对于类适配器,适配器可以重定义Adaptee的部分行为,相当于子类覆盖父类的部分实现方法。
对于对象适配器,要重定义Adaptee的行为比较困难,这种情况下,需要定义Adaptee的子类来实现重定义,然后让适配器组合子类。虽然重定义Adaptee的行为比较困难,但是想要增加一些新的行为则方便的很,而且新增加的行为可同时适用于所有的源。
对于类适配器,仅仅引入了一个对象,并不需要额外的引用来间接得到Adaptee。
对于对象适配器,需要额外的引用来间接得到Adaptee。
建议尽量使用对象适配器的实现方式,多用合成/聚合、少用继承。当然,具体问题具体分析,根据需要来选用实现方式,最适合的才是最好的。
适配器模式的优点
- 更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
- 更好的扩展性
在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
适配器模式的缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。