设计模式之创建型模式

创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。

创建型模式分为以下几种。
单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
工厂方法(FactoryMethod)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。

以上 5 种创建型模式,除了工厂方法模式属于类创建型模式其他的全部属于对象创建型模式

1.单例模式

单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式
单例模式有 4 个特点:

  1. 单例类只有一个实例对象;
  2. 该单例对象必须由单例类自行创建;
  3. 单例类对外提供一个访问该单例的全局访问点;
  4. 构造函数一般是私有,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。

1.1 懒汉式单例

该模式的特点是首先生成一个静态对象,类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。

public class LazySingleton
{
    private static volatile LazySingleton instance=null;    //第一层锁:保证变量可见性
    //构造函数私有,避免类在外部被实例化
    private LazySingleton(){} 
    //公有静态函数,对外暴露获取单例对象的接口   
    public static synchronized LazySingleton getInstance()
    {
        if(instance==null){//第一次判断空:无需每次加锁,提高性能
            synchronized(LazySingleton.class){//第二次层锁:保证线程同步
           		 if(instance==null){
            		instance=new LazySingleton();//第二次判空,避免多线程同时调用getinstance 产生多个instance对象
           		 }
           	}    
        }
        return instance;
    }
}

如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程非安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。懒汉单例模式的优点是单例只有在使用时才会被实例化,在一定程度上节约了资源

1.2 饿汉式单例

该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。

public class HungrySingleton
{
    private static final HungrySingleton instance=new HungrySingleton();
    private HungrySingleton(){}
    public static HungrySingleton getInstance()
    {
        return instance;
    }
}

饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。

1.3 静态内部类单例模式

当第一次加载Singleton类时并不会初始化sInstance,只有在第一次调用Singleton的getInstance
方法时才会导致sInstance被初始化。因此,第一次调用getInstance方法会导致虚拟机加载
SingletonHolder类,这种方式不仅能够确保线程安全,也能够保证单例对象的唯一性, 同时也延迟
了单例的实例化,所以这是推荐使用的单例模式实现方式。

public class Singleton {
	private Singleton() { }
	public static Singleton getInstance () {
		return Single tonHolder . sInstance;
	}
/*静态内部类*/
	private static class SingletonHolder {
		private static final Singleton sInstance = new Singleton() ;
	}
}

1.4 单例模式的应用场景

前面分析了单例模式的结构与特点,以下是它通常适用的场景的特点。
在应用场景中,某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。
当某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。

1.5 单例模式的优缺点

优点
(1)由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地创建、
销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。
(2)由于单例模式只生成一个实例,所以,减少了系统的性能开销,当一个对象的产生需要比
较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对
象,然后用永久驻留内存的方式来解决。
(3)单例模式可以避免对资源的多重占用,例如一个写文件操作,由于只有一个实例存在内存
中,避免对同一个资源文件的同时写操作。
(4)单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如,可以设计一个单例
类,负责所有数据表的映射处理。
缺点
(1)单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可
以实现。
(2)单例对象如果持有Context,那么很容易引发内存泄漏,此时需要注意传递给单例对象的
Context最好是Application Context。

2.原型模式

原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。

2.1 模式的结构

原型模式包含以下主要角色:
抽象原型类:规定了具体原型对象必须实现的接口。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象。

2.2 模式的实现

原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下:

//具体原型类
class Realizetype implements Cloneable
{
    Realizetype()
    {
        System.out.println("具体原型创建成功!");
    }
    public Object clone() throws CloneNotSupportedException
    {
        System.out.println("具体原型复制成功!");
        return (Realizetype)super.clone();
    }
}
//原型模式的测试类
public class PrototypeTest
{
    public static void main(String[] args)throws CloneNotSupportedException
    {
        Realizetype obj1=new Realizetype();
        Realizetype obj2=(Realizetype)obj1.clone();
        System.out.println("obj1==obj2?"+(obj1==obj2));
    }
}

2.3 原型模式的应用场景

原型模式通常适用于以下场景:
对象之间相同或相似,即只是个别的几个属性不同的时候。
对象的创建过程比较麻烦,但复制比较简单的时候。

2.4 原型模式的扩展

在这里插入图片描述

3.工厂方法模式

工厂方法(FactoryMethod)模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中

3.1 优缺点

工厂方法模式的主要优点有:
用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

其缺点是:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

3.2 模式的结构与实现

工厂方法模式由抽象工厂、具体工厂、抽象产品和具体产品等4个要素构成。本节来分析其基本结构和实现方法。
工厂方法模式的主要角色如下。
抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

3.3 模式的应用场景

工厂方法模式通常适用于以下场景。
客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
客户不关心创建产品的细节,只关心产品的品牌。
模式的扩展
当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类。这时工厂方法模式将退化到简单工厂模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值