概述
《设计模式》一书,正式和详细地描述了23种基本的设计模式。它将这些设计模式划分为3类:创建型模式,行为型模式,结构型模式。
创建类模式
简述
主要关注对象的创建过程,将对象的创建过程进行封装,使客户端可以直接得到对象,而不用去关心如何创建对象。创建类模式有5种,分别是:
- 单例模式:用于得到内存中的唯一对象。
- 工厂方法模式:用于创建复杂对象。
- 抽象工厂模式:用于创建一组相关或相互依赖的复杂对象。
- 建造者模式:用于创建模块化的更加复杂的对象。
- 原型模式:用于得到一个对象的拷贝。
为什么需要创建性模式
首先,在编程中,对象的创建通常是一件比较复杂的事,因为,为了达到降低耦合的目的,我们通常采用面向抽象编程的方式,对象间的关系不会硬编码到类中,而是等到调用的时候再进行组装,这样虽然降低了对象间的耦合,提高了对象复用的可能,但在一定程度上将组装类的任务都交给了最终调用的客户端程序,大大增加了客户端程序的复杂度。采用创建类模式的优点之一就是将组装对象的过程封装到一个单独的类中,这样,既不会增加对象间的耦合,又可以最大限度的减小客户端的负担。
其次,使用普通的方式创建对象,一般都是返回一个具体的对象,即所谓的面向实现编程,这与设计模式原则是相违背的。采用创建类模式则可以实现面向抽象编程。客户端要求的只是一个抽象的类型,具体返回什么样的对象,由创建者来决定。
再次,可以对创建对象的过程进行优化,客户端关注的只是得到对象,对对象的创建过程则不关心,因此,创建者可以对创建的过程进行优化,例如在特定条件下,如果使用单例模式或者是使用原型模式,都可以优化系统的性能。
总结
所有的创建类模式本质上都是对对象的创建过程进行封装。
#
1.单例模式
定义:
确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
1.1枚举类单例
public enum EasySingleton{
INSTANCE;
}
我通过EasySingleton.INSTANCE来访问实例。
创建枚举默认就是线程安全的
而且还能防止反序列化导致重新创建新的对象。
1.2静态内部类
也是一种懒加载模式
public class Singleton {
/* 私有构造方法,防止被实例化 */
private Singleton() {
}
/* 此处使用一个内部类来维护单例 */
private static class SingletonFactory {
private static Singleton instance = new Singleton();
}
/* 获取实例 */
public static Singleton getInstance() {
return SingletonFactory.instance;
}
/* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */
public Object readResolve() {
return getInstance();
}
}
这种写法仍然使用JVM本身机制保证了线程安全问题;由于SingletonHander是私有的,除了getInstance()之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖与JDK版本。
饿汉式
这种方法非常简单,因为单例的实例被声明成 static 和 final 变量了,在第一次加载类到内存中时就会初始化,所以创建实例本身是线程安全的。
public class Singleton{
//类加载时初始化
private static final Singleton instance=new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
这种写法如果完美的话,就没必要在啰嗦那么多双检锁的问题了。缺点是它不是一种懒加载模式(lazy initialization),单例会在加载类后一开始就被初始化,即使客户端没有调用 getInstance()方法。饿汉式的创建方式在一些场景中将无法使用:譬如 Singleton 实例的创建是依赖参数或者配置文件的,在 getInstance() 之前必须调用某个方法设置参数给它,那样这种单例写法就无法使用了。
单例模式的优点
- 在内存中只有一个对象,节省内存空间。
- 避免频繁的创建销毁对象,可以提高性能
- 避免对共享资源的多重占用
- 可以全局访问
使用场景
- 所有要求只有一个对象的场景 需要频繁实例化然后销毁的对象
- 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
- 有状态的工具类对象
- 频繁访问数据库或文件的对象
2.工厂模式
定义:
需要创建复杂对象的地方,适合使用工厂模式,通过工厂来创建对象实例,用于降低对象耦合性,将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式分为三类:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。
三种模式应用场景类似,这里着重介绍简单工厂模式,并通过示例介绍java反射机制与工厂模式的结合。
简单工厂模式:
又称为静态工厂方法模式,存在的目的很简单:定义一个用于创建对象的接口。
在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化, 如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样。
组成有三个角色:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
简单工厂模式示例
interface Fruit{
public void eat();
}
class Apple implements Fruit{
public void eat(){
System.out.println("吃苹果。");
}
}
class Orange implements Fruit{
public void eat(){
System.out.println("吃橘子");
}
}
class Factory{
//工厂类
public static Fruit getInstance(String className){ //注意这里为静态方法
Fruit f=null;
if(className.equals("apple")){
f=new Ap