设计模式之创建型2
本文学习自大话设计模式
设计模式之创建型
1. 单例模式
单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式有5种基本实现方式。
-
饿汉单例
线程安全,非懒加载,直接创建实例
public class EhSingleton{ private static EhSingleton ehSingleton = new EhSingleton(); private EhSingleton(){} public static EhSingleton getInstance(){ return ehSingleton; } }缺点:类加载就初始化,浪费内存。
优点:没有加锁,执行效率高,线程安全。
-
懒汉单例
线程不安全,懒加载
public class LazySingleton{ private static LazySingleton lazySingleton; private LazySingleton(){} public static LazySingleton getInstance(){ if(lazySingleton == null){ lazySingleton = new LazySingleton(); } return lazySingleton; } } -
加同步锁的懒汉单例
线程安全,懒加载
public class LazySingletonSync{ private static LazySingleSync lazySingletonSync; private LazySingletonSync(){} public static synchronized LazySingletonSync getInstance(){ if(lazySingletonSync == null){ lazySingletonSync = new LazySingletonSync(); } return lazySingletonSync; } }问题:效率低,只有第一次调用初始化之后才需要同步,初始化之后都不需要同步。锁的粒度太大,影响程序的执行效率。
-
双重检验懒汉单例
线程安全,懒加载
使用
synchronized声明的方法,在多线程访问时,其他线程必须等待前面的线程执行完毕之后才能访问,降低了程序的执行效率,这个时候使用synchronized代码块优化执行时间,减小锁的粒度。public class LazySingletonDoubleCheck{ private static LazySigletonDoubleCheck lazySingletonDoubleCheck; private LazySingletonDoubleCheck(){} public static LazySingletonDoubleCheck getInstance(){ if(lazySingletonDoubleCheck == null){ scnchronized(LazySingletonDoubleCheck.class){ if(lazySingleDoubleCheck == null){ lazySigletonDoubleCheck = new LazySingletonDoubleCheck(); } } } return lazySingletonDoubleCheck; } } -
静态内部类
线程安全,懒加载
public class StaticClass { private StaticClass() {} private static class SingletonHolder { private static final SingletonHolder INSTANCE = new SingletonHolder(); } public static final SingletonHolder getInstance() { return SingletonHolder.INSTANCE; } }
2. 建造者模式
建造者模式就是一个规范化的过程。要使用到抽象的类来定义基本的模块。
建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
-
建造者模式的结构图
![image-20220720114205422]()
Builder:建造产品各个部分的抽象类;
ConcreteBuilder:具体的产品,实现抽象类中定义的各个部分;
Director:指挥者,构建一个使用Builder接口的对象;
-
建造房子为例
- 复杂房屋类
//复杂产品房子 public class House { private String baise; private String wall; private String roofed; public String getBaise() { return baise; } public void setBaise(String baise) { this.baise = baise; } public String getWall() { return wall; } public void setWall(String wall) { this.wall = wall; } public String getRoofed() { return roofed; } public void setRoofed(String roofed) { this.roofed = roofed; } }-
Bulider抽象类
//抽象建设者,主要用来指定建设步骤 public abstract class HouseBuilder { protected House house = new House(); //建设房屋的基本方法,建设根基、建设墙、建设屋顶 public abstract void buildBasic(); public abstract void buildWalls(); public abstract void roofed(); public House buildHouse() { return house; } } -
两个实现类
//高楼大厦 public class HighBuilding extends HouseBuilder{ @Override public void buildBasic() { System.out.println("高楼地基"); } @Override public void buildWalls() { System.out.println("高楼墙面"); } @Override public void roofed() { System.out.println("高楼屋顶"); } } //普通房屋 public class CommonHouse extends HouseBuilder{ @Override public void buildBasic() { System.out.println("普通房子基地"); } @Override public void buildWalls() { System.out.println("普通房子墙面"); } @Override public void roofed() { System.out.println("普通房子屋顶"); } } -
Director类
public class HouseDirector{ HouseBuilder houseBuilder = null; //构造器创建bilder对象 public HouseBuilder(HouseBuilder houseBuilder){ this.houseBuilder = houseBuilder; } //通过set方法设置对象属性 public void setHouseBuilder(HouseBuilder houseBuilder){ this.houseBuilder = houseBuilder; } //建造房屋的流程交给指挥者 public House constructHouse(){ hosueBuilder.buildBasic(); houseBuilder.buildWalls(); houseBuilder.roofed(); return houseBuilder.buildHouse(); } }
3. 原型模式
原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
-
原型模式结构图
![image-20220720121124924]()
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
- 抽象原型类(Prototype):规定了具体原型对象必须实现的接口。
- 具体原型类(ConcretePrototype):实现抽象原型类的clone方法,它是被复制的对象。
- 访问类(Client):使用具体的原型类中的clone方法来复制新的对象
-
原型模式的例子
-
原型类代码
重点是实现Cloneable接口以及重写clone方法
public class Prototype implements Cloneable, Serializable { private String name; private int age; private RefObject refObject; public Prototype(String name, int age) { this.name = name; this.age = age; } public RefObject getRefObject() { return refObject; } public void setRefObject(RefObject refObject) { this.refObject = refObject; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } //重写克隆方法 默认浅拷贝 @Override protected Object clone() throws CloneNotSupportedException { Prototype clone = (Prototype) super.clone(); return clone; } @Override public String toString() { return "Prototype{" + "name='" + name + '\'' + ", age=" + age + ", refObject=" + refObject + '}'; } } -
客户端main方法
public static void main(String[] args) throws CloneNotSupportedException { Prototype prototype = new Prototype("原型模板",2); prototype.setRefObject(new RefObject()); Prototype clone1 = (Prototype) prototype.clone(); Prototype clone2 = (Prototype) prototype.clone(); System.out.println(clone1); System.out.println(clone2); System.out.println("原型 hashCode"+prototype.getRefObject().hashCode()); System.out.println("浅克隆 hashCode"+clone1.getRefObject().hashCode()); System.out.println("浅克隆 hashCode"+clone2.getRefObject().hashCode()); System.out.println(prototype.getRefObject()==clone1.getRefObject()); System.out.println(prototype.getRefObject()==clone2.getRefObject()); }
-
-
原型模式深拷贝
//深拷贝 利用反序列 和序列化 @Override protected Object clone() { //序列化 将当前对象序列化到内存中 ByteArrayOutputStream byteArrayOutputStream; ObjectOutputStream oos = null; ObjectInputStream ois = null; try { byteArrayOutputStream = new ByteArrayOutputStream(); oos = new ObjectOutputStream(byteArrayOutputStream); oos.writeObject(this); //反序列化 byte[] bytes = byteArrayOutputStream.toByteArray(); ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ois = new ObjectInputStream(bis); return ois.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } finally { if (oos != null) { try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } if (ois != null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } -
原型模式的优缺点
- 优点:
- java自带的原型模式基于内存二进制流的复制,在性能上比new一个对象更加优良。
- 可以使用深拷贝保存对象的状态,以便后续使用。
- 缺点:
- 在java中需要为每个类都配置一个clone方法。
- clone方法位于类内部,改造类的时候需要修改代码。
- 深拷贝的实现比较复杂,需要每一层对象对应的类都需要支持深拷贝。
- 优点:


浙公网安备 33010602011771号