java设计模式总结(二) ---- 五种创建型模式(引用一下韩老师的代码)
设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
https://www.cnblogs.com/fswhq/p/sjms.html 这是我看见的一位大佬的文章可以,看一下
创建模式(5种)
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
1,单例设计模式
定义:确保一个类最多只有一个实例,并提供一个全局访问点
八种方式:
1> 饿汉式(静态常量)
2> 饿汉式(静态代码块)
3> 懒汉式(线程不安全)
4> 懒汉式(同步方法)
5> 懒汉式(同步代码块)
6> 双重检查
7> 静态内部类
8> 枚举
1.1饿汉式(静态常量)
class Singleton { //1. 构造器私有化, 外部能new private Singleton() { } //2.本类内部创建对象实例 private final static Singleton instance = new Singleton(); //3. 提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
优点:简单,没有线程安全问题
缺点:老友Lazy Loading效果,没有使用该单例时,浪费内存
1.2饿汉式(静态代码块)
class Singleton { //1. 构造器私有化, 外部能new private Singleton() { } //2.本类内部创建对象实例 private static Singleton instance; static { // 在静态代码块中,创建单例对象 instance = new Singleton(); } //3. 提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
优缺点和上面一种饿汉式差不多
1.3懒汉式(线程不安全)
class Singleton { private static Singleton instance; private Singleton() {} //提供一个静态的公有方法,当使用到该方法时,才去创建 instance //即懒汉式 public static Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } }
优缺点:
有Lazy Loading的效果,只能在单线程下使用
多线程下会出现多个实例
不要使用这种方式
class Singleton { private static Singleton instance; private Singleton() {} //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题 //即懒汉式 public static synchronized Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } }
优缺点:没有线程安全问题
效率太低,每次都要进去都要同步
1.5懒汉式(线程安全,同步代码块)
// 懒汉式(线程安全,同步方法) class Singleton { private static Singleton instance; private Singleton() {} //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题 //即懒汉式 public static Singleton getInstance() { if(instance == null) { synchronized(Singleton.class){ instance = new Singleton(); } } return instance; } }
多线程时会产生多例
1.6 双重检查
class Singleton { private static volatile Singleton instance; private Singleton() {} //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题 //同时保证了效率, 推荐使用 public static synchronized Singleton getInstance() { if(instance == null) { synchronized (Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; } }
优缺点:线程安全;延迟加载;效率高
1.7 静态内部类
// 静态内部类完成, 推荐使用 class Singleton { private static volatile Singleton instance; //构造器私有化 private Singleton() {} //写一个静态内部类,该类中有一个静态属性 Singleton private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE public static synchronized Singleton getInstance() { return SingletonInstance.INSTANCE; } }
优缺点:使用类加载机制;使用时在实例化;第一次加载时才初始化jvm保证单例
1.8 枚举
//使用枚举,可以实现单例, 推荐 enum Singleton { INSTANCE; //属性 }
JDK5.0新特性,还防止了序列化
1.9单例模式在JDK中的使用
使用的饿汉式
1.10细节说明和使用事项
1 工厂模式(包括简单工厂,工厂方法,抽象工厂)
1.1 简单工厂模式
定义:定义了一个创建对象的类,由这个类来封装实例化对象的行为。
举例:(我们举一个pizza工厂的例子)
使用简单工厂:
public Pizza createPizza(String orderType) { Pizza pizza = null; System.out.println("使用简单工厂模式"); if (orderType.equals("greek")) { pizza = new GreekPizza(); pizza.setName(" 希腊披萨 "); } else if (orderType.equals("cheese")) { pizza = new CheesePizza(); pizza.setName(" 奶酪披萨 "); } else if (orderType.equals("pepper")) { pizza = new PepperPizza(); pizza.setName("胡椒披萨"); } return pizza; }
1.2 工厂方法模式
定义:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
举例:(我们依然举pizza工厂的例子,不过这个例子中,pizza产地有两个:伦敦和纽约)。添加了一个新的产地,如果用简单工厂模式的的话,我们要去修改工厂代码,并且会增加一堆的if else语句。而工厂方法模式克服了简单工厂要修改代码的缺点,它会直接创建两个工厂,纽约工厂和伦敦工厂。类图如下:
在简单工厂的基础上增加了多个工厂,就让一个父类工厂去管理
子类的主要代码和简答工厂差不多
public class BJOrderPizza extends OrderPizza { @Override Pizza createPizza(String orderType) { Pizza pizza = null; if(orderType.equals("cheese")) { pizza = new BJCheesePizza(); } else if (orderType.equals("pepper")) { pizza = new BJPepperPizza(); } // TODO Auto-generated method stub return pizza; } }
1.3 抽象工厂模式
定义:定义了一个接口用于创建相关或有依赖关系的对象族,而无需明确指定具体类。
举例:(我们依然举pizza工厂的例子,pizza工厂有两个:纽约工厂和伦敦工厂)。类图如下:
//一个抽象工厂模式的抽象层(接口) public interface AbsFactory { //让下面的工厂子类来 具体实现 public Pizza createPizza(String orderType); }
把工厂方法模式加到接口之中,区别感觉不大
1.4工厂在JDK中的使用
在Calader中使用了简单工厂模式,根据时区来创建相应的子类对象
总结:工厂的好处,在创建的对象的时候我们会有各种各样的要求,我们把这一部分都讲给工厂去处理。我们在使用的时候只需要用方法区获取到类就行。不代码分离开
简单工厂:根据条件new
工厂方法:用父类来管理相似的工厂类
抽象工厂模式:用接口来管理相关的工厂类
ps:该模式是违反ocp原则的,对于新类工厂无法进行扩展。因为要去改工厂原本的方法
3原型模式
原型模式就是对一个类进行复制,在Cloneable接口中已经实现了,我们重写一下就行
@Override protected Object clone() { Sheep sheep = null; try { sheep = (Sheep)super.clone(); } catch (Exception e) { // TODO: handle exception System.out.println(e.getMessage()); } // TODO Auto-generated method stub return sheep; }
深拷贝和浅拷贝:如果我们在clone方法中,拷贝对于类中以其他类作为属性时,我们把他指向同一个对象,这样复制出来的过程叫浅拷贝,否则,就是深拷贝。如下图
浅拷贝:
我们的类属性:
重写clone:
客户端复制:
运行结果:
上图就是浅拷贝。
下面是深拷贝,有两种方式,方式一在复制属性对象时我们把该对象里面的clone也重新并且调用:
public String name; //String 属性 public DeepCloneableTarget deepCloneableTarget;// 引用类型 public DeepProtoType() { super(); } //深拷贝 - 方式 1 使用clone 方法 @Override protected Object clone() throws CloneNotSupportedException { Object deep = null; //这里完成对基本数据类型(属性)和String的克隆 deep = super.clone(); //对引用类型的属性,进行单独处理 DeepProtoType deepProtoType = (DeepProtoType)deep; deepProtoType.deepCloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone(); // TODO Auto-generated method stub return deepProtoType; }
方式二,进行序列化,再进行反序列化:
public String name; //String 属性 public DeepCloneableTarget deepCloneableTarget;// 引用类型 public DeepProtoType() { super(); } public Object deepClone() { //创建流对象 ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; ByteArrayInputStream bis = null; ObjectInputStream ois = null; try { //序列化 bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(this); //当前这个对象以对象流的方式输出 //反序列化 bis = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bis); DeepProtoType copyObj = (DeepProtoType)ois.readObject(); return copyObj; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); return null; } finally { //关闭流 try { bos.close(); oos.close(); bis.close(); ois.close(); } catch (Exception e2) { // TODO: handle exception System.out.println(e2.getMessage()); } } }
原型设计模式在Spring bean设置当中使用了
以上就是原型模式的全部内容。
4 建造者模式(生成器模式)
作用:把一个复杂的对象,内部结构和操作分离开来。内部结构不呈现给用户
以造房子为例,传统方式
画红线处,操作在用户用体现。
使用建造者模式:
指挥者去完成功能
在JDK--StringBuilder中的应用
好了,五中创建型模式就写到这儿,我写的东西不会放全部代码,会多给原理图和重要代码截图