Skip to content

Latest commit

 

History

History
269 lines (211 loc) · 9.59 KB

File metadata and controls

269 lines (211 loc) · 9.59 KB

0. 单例+简单工厂+工厂+抽象工厂+生成器+原型模式

1. 单例(Singleton)

  • 概念:确保一个类在程序全局中只有一个实例,并只提供了一个全局的唯一访问点。最典型的就是Logger的创建。因为仅仅需要一个logger就可以满足全局的使用。

  • 使用一个私有无参构造函数private Signleton(){}保证不能通过构造函数进行单例对象的实例化。

  • 使用一个私有变量private Signleton uniqueInstance;(一般是静态的)来保证这个单例只有一个对象能够进行访问

  • 使用一个公有的访问点public Signleton getInstance(){}来对该单例中的唯一私有变量进行访问

  • 懒汉式:线程不安全,在第一次调用get方法时才对对象进行实例化(即new一个单例到达私有变量中),但若多个线程同时到达get方法中,则可能同时new多个单例对象

public class Singleton {

    private static Singleton uniqueInstance;

    private Singleton() {
    }

    public static Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}
  • 饿汉式:线程安全,在一开始直接将单例变量进行实例化,不会进入if判断,也不会new,但是若该单例一直未被使用,则十分消耗资源。
  • 懒汉式-线程安全:为get方法加上synchronized修饰,一次只有一个方法能够进入并获取实例,虽然线程安全,但是效率偏低
  • 双重校检锁:对get方法中的是否实例化进行对次判断并添加synchronized进行修饰,为实例变量添加volatile进行轻量级锁修饰,防止在多线程下呗jvm进行指令重排,即先分配内存空间,在初始化对象,则中间调用时会调用到有地址为初始化的对象实例
public class Singleton {

    private volatile static Singleton uniqueInstance;

    private Singleton() {
    }

    public static Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}
  • 静态内部类:将私有实例变量以private static final Singleton INSTANCE = new Singleton();后放在单例中的一个静态内部类中,在调用get时,才会初始化静态内部类,再在类加载时对其中的静态变量进行初始化。静态变量的加载过程中,有jvm保证了线程安全的特性
  • 枚举实现:在保证了线程安全和其他特性的基础上,枚举实现还可以防止单例被反射攻击,即使暴力反射也不能获得多个单例实例。枚举的构造函数天生别第一位static final,其只会被实例化一次,故通过jvm就可以保证其单例的实现和线程安全,以及防止反射攻击的可能
class Test{
    SomeThing.INSTANCE.getIntance(); //获得枚举类中的唯一实例
}

public enum SomeThing {
    INSTANCE;
    private Test instance;
    SomeThing {
        instance = new Test;
    }
    public Test getInstance() {
        return instance;
    }
}
//枚举类自身实现了序列化接口,能够有利于序列化操作
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable

2 简单工厂(Simple Factory)

  • 概念:在创建一个对象时不向创建者暴露细节,而是调用工厂来进行实例化并返回。
  • 该工厂下的所有需要创建的对象都使用了一个公用接口,以便调用时能够使用向下转型
  • 在工厂类中使用构造函数重载的形式来对需要返回的类型进行判断
//定义一个公共接口,工厂中的所有类都继承这个接口
public interface PublicClass{}
public class implement1 implements PublicClass{}
public class implement2 implements PublicClass{}
public class implement3 implements PublicClass{}

public class SimpleFactory{
    public PublicClass creatClass(int x) {
        if(x == 1) {
            return new implement1();//调用create方法时就将对象new出去,以便接收使用
        } else if(x == 2) {
            return new implement2();
        }
        //.......
    }
}

public class Client{
    public static void main(String[] args) {
        SimpleFactory sf = new SimpleFactory();
        PublicClass pc1 = sf.creatClass(1);//直接通过接口来创建一个具体的类对象,类似集合的创建
    }
}

3. 工厂方法(Factory Method)

  • 概念:在使用了接口之后,使用一个抽象类来进行工厂的简易实现,每一个实现类都添加一个实现工厂基础抽象类的工厂。一次只会返回一个相关的接口类
public abstract class Factory{
    public abstract PublicClass factoryMethod();//用于创建该接口不同实现类的不同工厂实现
    public void doSomeThing() {
        PublicClass pc = factoryMethod();
        //一些接口相关的公有事项方法
    }
}

public class ConcreteFactory1 extends Factory{
    public PublicClass factoryMethod(){  //实现工厂中的抽象方法,并返回特定的接口实类
        return class1;
    }
}

4. 抽象工厂(Abstract Factory)

  • 概念:和工厂类似,也提供共有接口,但是返回一个对象家族,即多个相关联的对象
  • 通过多个父接口描述一个具体对象,对接口进行实现,每个接口的实现有多个
  • 将多个工厂放入到抽象工厂中,调用抽象工厂返回具体工厂,工厂继承抽象工厂来对具体需要返回的对象进行查找并返回
  • 再通过调用工厂得到返回的对象并使用
//抽象工厂
public abstract class AbstractFactory {
    abstract AbstractProductA createProductA();
    abstract AbstractProductB createProductB();
}

//工厂的具体实现,继承自抽象工厂
public class ConcreteFactory1 extends AbstractFactory {
    AbstractProductA createProductA() {//返回的具体类由其接口来接收,
        return new ProductA1();
    }

    AbstractProductB createProductB() {
        return new ProductB1();
    }
}

5. 建造者(Builder)

  • 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。

  • 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。

  • 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。

  • 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

  • 相同的方法,不同的执行顺序,产生不同的结果

  • 多个部分或零件,都可以装配到一个对象中,但是产生的结果是不一样的

  • 产品类十分的复杂,或者产品类中不同的调用顺序产生不同的结果

  • 初始化一个对象非常复杂,参数多,而且很多参数都有默认值

(1) 产品角色:包含多个组成部件的复杂对象。

class Product {    
    private String partA;    
    private String partB;    
    private String partC;    
    public void setPartA(String partA) {
        this.partA = partA;    
    }    
    public void setPartB(String partB) {
        this.partB = partB;    
    }   
    public void setPartC(String partC) {
        this.partC = partC;    
    }    
    public void show() {
        //显示产品的特性    
    }
}

(2) 抽象建造者:包含创建产品各个子部件的抽象方法。

abstract class Builder {    //创建产品对象    
    protected Product product = new Product();    
    public abstract void buildPartA();    
    public abstract void buildPartB();    
    public abstract void buildPartC();    
    //返回产品对象    
    public Product getResult() {
        return product;    
    }}

(3) 具体建造者:实现了抽象建造者接口。

public class ConcreteBuilder extends Builder {    
    public void buildPartA() {        
        product.setPartA("建造 PartA");    
    }   
    public void buildPartB() {
        product.setPartB("建造 PartB");    
    }    
    public void buildPartC() {
        product.setPartC("建造 PartC");    
    }
}

(4) 指挥者:调用建造者中的方法完成复杂对象的创建。

class Director {    
    private Builder builder;    
    public Director(Builder builder) {
        this.builder = builder;    
    }    //产品构建与组装方法    
    public Product construct() {
        builder.buildPartA();        
        builder.buildPartB();        
        builder.buildPartC();        
        return builder.getResult();    
    }
}

(5) 客户类。

public class Client {    
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();        
        Director director = new Director(builder);       
        Product product = director.construct();        
        product.show();    
    }
}

6. 原型模式

  • 通过复制将一个对象实例clone()为另一个对象实例,能够在一定程度上减少资源的消耗

  • java中可以直接通过实现Cloneable接口来使用clone()方法直接实现对象的复制,java中提供的clone方法时浅拷贝的实现

  • 也即是在对象内部实现clone方法,能够用于保存类的实时信息,用于快照存储等用途

  • 缺点也很明显,一般用的很少?