简约的理解创建型模式就是和创建对象相关的设计模式,它主要包含了6种设计模式:
1) 单例模式
2) 建造者模式
3) 原型模式
4) 简单工厂模式
5) 工厂方法模式
6) 抽象工厂模式
定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.
UML类图:
其中Client——高层客户端;Singleton——单例类
实现单例模式的几个关键点:
1) 构造函数不对外开放,一般为private
2) 通过一个静态方法或者枚举返回单例类对象
3) 确保单例类对象只有一个
4) 确保单例类对象在反序列化时不会重新构建对象.
实现单例模式有饿汉单例模式、懒汉单例模式、DCL实现单例、静态内部类单例模式、枚举单例、容器实现单例模式.
饿汉单例模式:在类中声明一个静态对象并初始化,对外开放一个静态方法用于返回该静态对象,以此实现单例模式.
/** * 饿汉单例模式 */ publicclassSingleton{ //创建静态对象并初始化 privatestaticfinal Singleton singleton =newSingleton(); privateSingleton(){ } //对外开发的方法,并返回静态对象 publicstaticSingletongetInstance(){ returnsingleton; } }
懒汉单例模式:在类中声明一个静态对象,并且在用户第一次调用getInstance()方法时才对其进行初始化.这里和饿汉单例模式的区别就在于单例对象创建的时间不同.其优点在于只有在使用时才会被实例化;其缺点就是第一次加载时需要及时实例化,反应稍慢,最大的问题就是每次调用getInstance方式都需要进行同步.
/** * 懒汉单例模式 */ publicclassSingleton{ privatestaticSingleton singleton; privateSingleton(){ } /** * 若单例类对象为空,即第一次调用getInstance方法,则先创建再返回;若单例对象已经创建过了,那么直接返回 * @return */ publicstaticsynchronized SingletongetInstance(){ if(singleton==null){ singleton = newSingleton(); } returnsingleton; } }
Double Check Lock(DCL)实现单例: DCL方式实现单例模式的优点就是即能够在需要时才初始化单例,又能够保证线程安全,且单例对象初始化都调用getInstance不进行同步锁.
具体为在getInstance方法中采用两层判断:第一层判断是为了避免不必要的同步;第二层的判断则是为了在null的情况下创建实例.
/** * 单例模式 */ publicclassSingleton{ //(1) //private static Singleton singleton = null; //(2)在多线程环境下,(1)的语句就会出现问题,所以在JDK1.5之后,可以为变量加上一个关键字“volatile”来保证每次读取变量的值时,读取到的数据都是最新的. privatevolatilestaticSingleton singleton =null; privateSingleton(){ } publicstaticSingletongetInstance(){ if(singleton==null){ synchronized (Singleton.class) { if(singleton ==null){ singleton = newSingleton(); } } } returnsingleton; } }
静态内部类单例模式:这种方式不仅保证线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化.
privateSingleton(){ } publicstaticSingletongetInstace(){ returnSingletonHolder.sInstance; } //静态内部类 privatestaticclassSingletonHolder{ privatestaticfinalSingleton sInstance =newSingleton(); }
定义:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示.
使用场景:
1) 相同的方法不同的执行顺序,产生不同的事件结果;
2) 多个部件或者零件,都可以装配到一个对象中,但是产生的运行结果又不相同时;
3) 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时.
UML类图:
1) Product产品类——产品的抽象类;
2) Builder——抽象Builder类,规范产品的组建,一般由子类实现具体的组建过程;
3) ConcreteBuilder——具体的Builder类,实现产品每个组件的建造过程.
4) Director——统一组装过程(在平时使用时,通常不要这个类)
优点:良好的封装性,使用建造者模式可以使客户端不必知道产品内部组成的细节.易扩展
/** * 抽象Builder类,定义产品的组建步骤(如需要哪些组件) */ publicabstractclassBuilder{ publicabstractvoidbuildeWheel(String wheel); publicabstractvoidbuildeEngine(String engine); publicabstractvoidbuildeExterior(String exterior); publicabstractvoidbuildBrand(); publicabstractCarcreate(); } /** * 抽象产品类 */ publicabstractclassCar{ protectedString mWheel; protectedString mEngine; protectedString mExterior; protectedString mBrand; protectedCar(){ } publicabstractvoidsetmBrand(); //省略setter和getter @Override publicStringtoString(){ // TODO Auto-generated method stub return"Car [mWheel="+ mWheel +", mEngine="+mEngine +", mExterior="+ mExterior+", mBrand="+ mBrand +"]"; } } /** * 具体产品类 */ publicclassBMWCarextendsCar{ @Override publicvoidsetmBrand(){ // TODO Auto-generated method stub mBrand = "BMW x1"; } } /** * 具体Builder类 */ publicclassBMWCarBuilderextendsBuilder{ privateCar car =newBMWCar(); @Override publicvoidbuildeWheel(String wheel){ // TODO Auto-generated method stub car.setmWheel(wheel); } @Override publicvoidbuildeEngine(String engine){ // TODO Auto-generated method stub car.setmEngine(engine); } @Override publicvoidbuildeExterior(String exterior){ // TODO Auto-generated method stub car.setmExterior(exterior); } @Override publicvoidbuildBrand(){ // TODO Auto-generated method stub car.setmBrand(); } @Override publicCarcreate(){ // TODO Auto-generated method stub returncar; } } /** * 指导者类 */ publicclassDirector{ Builder mBuilder = null; publicDirector(Builder builder){ mBuilder = builder; } //构建对象 publicvoidconstruct(String wheel,String engine,String extrior){ mBuilder.buildeWheel(wheel); mBuilder.buildeEngine(engine); mBuilder.buildeExterior(extrior); } } //使用 publicclassMain{ publicstaticvoidmain(String[] args){ Builder builder = newBMWCarBuilder(); //builder.create().setmWheel("日产"); Director d = newDirector(builder); d.construct("","","");//传入参数 } }
定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象.
使用场景:(1)类初始化需要消化非常多的资源,这个资源包含数据、硬件资源等,通过原型拷贝避免这些浪费;
(2)通过new产生一个对象需要非常繁琐的数据准备或者访问权限;