建立型模式,就是建立对象的模式,抽象了实例化的过程。它帮助一个系统独立于如何建立、组合和表示它的那些对象。关注的是对象的建立,建立型模式将建立对象的过程进行了抽象,也能够理解为将建立对象的过程进行了封装,做为客户程序仅仅须要去使用对象,而再也不关心建立对象过程当中的逻辑html
定义:确保一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。
类图:java
主要有三个部分:数据库
私有的构造方法 指向本身实例的私有静态引用 以本身实例为返回值的静态的公有的方法
特色:*
优势:编程
在内存中只有一个对象,节省内存空间。 避免频繁的建立销毁对象,能够提升性能。 避免对共享资源的多重占用。 能够全局访问。
适用场景:安全
须要频繁实例化而后销毁的对象。 建立对象时耗时过多或者耗资源过多,但又常常用到的对象。 有状态的工具类对象。 频繁访问数据库或文件的对象等等。
注意事项:多线程
只能使用单例类提供的方法获得单例对象,不要使用反射,不然将会实例化一个新对象。 不要作断开单例类对象与类中静态引用的危险操做。 多线程使用单例使用共享资源时,注意线程安全问题。
饿汉式:ide
/** * 一:饿汉式(类加载的时候就建立了实例) * 优势:实现了线程安全,编写简单;执行效率高 * 缺点:初始化就建立了实例,对加载速度和内存有消耗,,因此这种方法要求单例对象初始化速度快且占用内存小 */ // 一、成员变量静态化 private static Singleton3 instance = new Singleton3(); //二、构造函数私有化,防止外部实例化 private Singleton3(){} //三、提供公共静态建立实例方法 public static Singleton3 getInstance(){ return instance; } /** * 二:枚举类型:根据枚举类型的特色,实现单例模式所须要的建立单例、线程安全、简洁的需求 * 优势:实现比较简洁,保证了单实例,线程安全 * 缺点:使用枚举类型,不是很熟悉 */ /** * 枚举类型的特色: * 一、枚举类型 = 不可被继承的类(final): * 枚举本质上是经过普通类实现的,只是编译器为咱们进行了特殊处理 * 每一个枚举类型都继承自java.lang.Enum,并自动添加了values(),valueOf() * 枚举类的实例 = 常量 * 二、每一个枚举元素 = 类静态常量 = 1个实例 * 枚举元素,都是经过静态代码来进行初始化,即在类加载期间进行初始化,保证了实例只被建立一次,线程安全 * 获取枚举元素 = 获取实例 * 三、构造方法 访问权限 默认=私有(private):他的构造器是私有的,底层没有可供调用的无参数的构造器;防止了其余人建立实例 * 四、每个枚举类型&枚举变量在JVM中都是惟一的: * 即java在序列化和反序列化美剧时作了特殊的规定:枚举的writeObject(),readObject(),readObjectNoData()等方法是被禁用的,所以不存在序列化接口以后调用readObject会破环单例的问题 * 保证了枚举元素的不可变行,即不能经过克隆、序列化&反序列化来复制枚举,即保证了1个枚举常量=1个实例 即单例 */ public enum Singleton { INSTANCE; public void whateverMethod() { } }
懒汉式:函数
//程序中建立类只有两种方式:1建立类的一个对象,用该对象去调用类中的方法;2使用类名直接调用类中方法,类名.方法名();单例模式防止外部new对象,只能使用类方法,且是静态的。 /** * 一:懒汉式(须要的时候建立实例),线程不安全。当多个线程同时访问时,不能正常工做。 * 优势:按需加载 * 缺点:线程不安全。多个线程同时访问时,会建立多个实例。 */ // 一、成员变量静态化 private static Singleton1 instance; //二、构造函数私有化,防止外部实例化 private Singleton1(){} //三、提供公共静态建立实例方法 public static Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } /** * 二:懒汉式:线程安全,加同步锁, * 优势:实现了线程安全 * 缺点:每次访问都要进行线程同步(调用synchronized锁),形成过多的同步开销(加锁=耗时、耗能) */ // 一、成员变量静态化 private static Singleton1 instance; //二、构造函数私有化,防止外部实例化 private Singleton1(){} //三、提供公共静态建立实例方法 public static synchronized Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } // 一、成员变量静态化 private static Singleton1 instance; //二、构造函数私有化,防止外部实例化 private Singleton1(){} //三、提供公共静态建立实例方法 public static Singleton1 getInstance() { synchronized(Singleton.class){ if (instance == null) { instance = new Singleton1(); } } return instance; } /** *三:懒汉式改进—双重校验锁;在同步锁的基础上,添加一层if判断,若单例已经建立,则不须要再执行加锁操做就能够获取实例,从而提升了性能。 *优势:避免了每次调用都要调用synchronized锁,同时双重校验又保证了线程安全,不会重复建立实例。 * 缺点:较为复杂,容易出错 */ // 一、成员变量静态化 private static Singleton1 instance = null; //二、构造函数私有化,防止外部实例化 private Singleton1(){} //三、提供公共静态建立实例方法 public static Singleton1 getInstance() { if (instance == null) { synchronized (Singleton1.class) { if (instance == null) { instance = new Singleton1(); } } } return instance; } /** * 四:静态内部类。在静态内部类中建立单例,在加载内部类时才会建立单例 * 优势:根据静态内部类的特性,实现了线程安全,按需加载,同时比较简洁 */ // 一、建立静态内部类 private static class Singleton2{ // 静态类里面建立单例 private static Singleton1 instance = new Singleton1(); } //二、构造函数私有化,防止外部实例化 private Singleton1(){} //三、提供公共静态建立实例方法 public static Singleton1 getInstance() { //调用静态类的实例方法 return Singleton2.instance; } /** * 调用过程说明 * 一、外部调用类的getInstance()方法 * 二、getInstance()方法自动调用内部类的方法,实现初始化 * 三、而该类在装载 & 被初始化时,会初始化他的静态域,从而建立单例 * 四、因为是静态域,所以JVM只会加载一遍,java虚拟机保证了线程安全 * 五、最终实现只建立一个实例。 */
定义:又静态工厂模式,能够根据参数的不一样返回不一样类的实例。
类图:工具
由此能够看出:简单工厂模式由三部分组成:具体工厂、具体产品和抽象产品性能
工厂类(Creator)角色:担任这个角色的是简单工厂模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下建立产品对象,它每每由一个具体Java类实现。 抽象产品(AbstractProduct)角色:担任这个角色的类是由简单工厂模式所建立的对象的父类,或它们共同拥有的接口。抽象产品角色能够用一个Java接口或者Java抽象类实现。 具体产品(ConcreteProduct)角色:简单工厂模式所建立的任何对象都是这个角色的实例,具体产品角色由一个具体Java类实现。
总结:
简单工厂只有一个工厂类,经过switch语句来区分建立哪一个产品。 工厂方法模式是扩展了简单工厂模式,区分为抽象工厂和具体工厂实现。
定义:定义一个建立对象的工厂接口,让子类决定实例化哪个类,将实际的建立工做推迟到子类当中。
类图:
工厂方法模式包含
抽象产品:通常是产品接口或者抽象产品类。主要目的是定义产品的规范,全部的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。 具体产品:实现产品接口的具体类,决定了产品在客户端中的具体行为。 抽象工厂:通常是工厂接口或者抽象工厂类。是工厂方法模式的核心,与调用者直接交互用来提供产品。 具体工厂:在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,须要有多少种产品,就须要有多少个具体的工厂实现。
优缺点:
优势:(1)封装了建立产品的方法,用户无须关心具体实现;(2)添加新产品时,只须要添加具体产品类和具体工厂类(实现或继承抽象产品、工厂类);(3)将建立工厂方法推迟到子类当中,实现了多态。工厂方法模式也叫多态工厂模式,之因此是多态,由于全部具体工厂类都具备同一父类。 缺点:(1)在添加新产品时,须要添加具体产品类、具体工厂类。当存在较多产品时,致使产品、产品工厂类增多,必定程度上增长了系统的复杂度,更多的类须要编译和运行,给系统带来了一些额外的开销。(2) 因为考虑到系统的可扩展性,须要引入抽象层,在客户端代码中均使用抽象层进行定义,增长了系统的抽象性和理解难度,且在实现时可能须要用到DOM、反射等技术,增长了系统的实现难度。
代码举例
//一、抽象产品类 public interface Moveable { public void run(); } //二、具体产品实现类 public class Car implements Moveable { @Override public void run() { System.out.println("小汽车!"); } } public class Plane implements Moveable { @Override public void run() { System.out.println("大飞机!"); } } //三、抽象工厂类 public abstract class Factory { public abstract Moveable create(); } //四、具体工厂实现类 public class CarFactory extends Factory { @Override public Moveable create() { return new Car(); } } public class PlaneFactory extends Factory { @Override public Moveable create() { return new Plane(); } } //测试类 public class FactoryTest { @Test public void FactoryTest(){ Factory car = new CarFactory(); Moveable m = car.create(); // Factory plane = new PlaneFactory(); // Moveable m= plane.create(); m.run(); } }
定义:提供一个建立一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
类图:
能够看到,抽象工厂模式也是包含抽象产品、具体产品、抽象工厂、具体工厂。
可是抽象工厂中有产品等级结构和产品族的概念。
产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不一样产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
和工厂方法模式的区别:
工厂方法模式提供的是一个产品等级结构的实现,抽象工厂模式提供多个不一样的产品等级结构的实现。
优缺点:
优势:能够在类的内部对产品族进行约束
缺点:产品族扩展比较麻烦。当增长新的产品时,全部的工厂类都要添加其相关代码。
代码举例:
//一、抽象产品类 public abstract class Vehicle{ public abstract void run(); } public abstract class Food { public abstract void printName(); } public abstract class Weapon { public abstract void shoot(); } //二、具体实现类 //第一个产品族 public class Car extends Vehicle { @Override public void run() { System.out.println("小汽车!"); } } public class Apple extends Food{ @Override public void printName() { System.out.println("红苹果"); } } public class AK47 extends Weapon { @Override public void shoot() { System.out.println("大火球,huhuhu。。。。。。"); } } //第2个产品族 public class Plane extends Vehicle { @Override public void run() { System.out.println("大灰机"); } } public class Pizza extends Food{ @Override public void printName() { System.out.println("披萨"); } } public class _98K extends Weapon{ @Override public void shoot() { System.out.println("砰砰砰。。。。。。"); } } //三、抽象工厂类 public abstract class AbstractFactory { public abstract Vehicle createVehicle(); public abstract Weapon createWeapon(); public abstract Food createFood(); } //四、具体工厂实现类 public class DefaultFactory extends AbstractFactory{ @Override public Vehicle createVehicle() { return new Car(); } @Override public Weapon createWeapon() { return new AK47(); } @Override public Food createFood() { return new Apple(); } } public class SuperFactory extends AbstractFactory{ @Override public Vehicle createVehicle() { return new Plane(); } @Override public Weapon createWeapon() { return new _98K(); } @Override public Food createFood() { return new Pizza(); } } //五、测试类 public class AbstractFactoryTest { @Test public void abstractFactoryTest(){ // AbstractFactory a = new DefaultFactory(); AbstractFactory a = new SuperFactory(); Vehicle v= a.createVehicle(); v.run(); Weapon w = a.createWeapon(); w.shoot(); Food f= a.createFood(); f.printName(); } }
总结:
定义:将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。
类图:
建造者模式包含四个要素:
产品类:通常是一个较为复杂的对象,也就是说建立对象的过程比较复杂,通常会有比较多的代码量。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类能够是由一个抽象类与它的不一样实现组成,也能够是由多个抽象类与他们的实现组成。 抽象建造者:引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。通常至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。 建造者:实现抽象类的全部未实现的方法,具体来讲通常是两项任务:组建产品;返回组建好的产品。 导演类:负责调用适当的建造者来组建产品,导演类通常不与产品类发生依赖关系,与导演类直接交互的是建造者类。通常来讲,导演类被用来封装程序中易变的部分。
优缺点:
优势:
将具体的业务逻辑实现封装在了导演类中,无须知道具体产品类的结构; 当添加新的产品时,只须要实现一个新的建造者类,并添加相应的导演类实现建立具体的产品。
代码实现:
class Product { private String name; private String type; public void showProduct(){ System.out.println("名称:"+name); System.out.println("型号:"+type); } public void setName(String name) { this.name = name; } public void setType(String type) { this.type = type; } } abstract class Builder { public abstract void setPart(String arg1, String arg2); public abstract Product getProduct(); } class ConcreteBuilder extends Builder { private Product product = new Product(); public Product getProduct() { return product; } public void setPart(String arg1, String arg2) { product.setName(arg1); product.setType(arg2); } } public class Director { private Builder builder = new ConcreteBuilder(); public Product getAProduct(){ builder.setPart("宝马汽车","X7"); return builder.getProduct(); } public Product getBProduct(){ builder.setPart("奥迪汽车","Q5"); return builder.getProduct(); } } public class Client { public static void main(String[] args){ Director director = new Director(); Product product1 = director.getAProduct(); product1.showProduct(); Product product2 = director.getBProduct(); product2.showProduct(); } }
与工厂模式的区别:
从结构上看,建造者模式只比工厂模式多了一个“导演类”的角色,若是没有这个导演类,就相似简单工厂模式了。
工厂模式是将对象的建立过程封装在工厂类中,由工厂类向客户端提供最终的产品。
建造者模式中,建造类通常只提供产品类中各个组件的建造,而将具体的建造过程交由导演类,由导演类实现具体的产品。
因此建造者模式通常用来建立更复杂的对象。
待续。
http://design-patterns.readth...
https://www.w3cschool.cn/java...