xqw的个人博客

Posted on By xqw

  • content {:toc}

1、单例

//饿汉模式,很饿很着急,所以类加载时即创建实例对象
public class Singleton1 {
    private static Singleton1 singleton = new Singleton1();

    private Singleton1() {
    }

    public static Singleton1 getInstance() {
        return singleton;
    }
}

//饱汉模式(懒汉),很饱不着急,延迟加载,啥时候用啥时候创建实例,存在线程安全问题
public class Singleton2 {
    private static Singleton2 singleton;

    private Singleton2() {
    }

    public static synchronized Singleton2 getInstance() {
        if (singleton == null)
            singleton = new Singleton2();
        return singleton;
    }
}

//饱汉模式的双重锁模式,提高效率
public class Singleton3 {
    //使用volatile 关键字修饰,防止指令重排
    //若发生指令重排,可能出现new Singleton3();时还没初始化完成(仅仅分配内存)就赋值给singleton
    //这时有另外的线程获取对象就是未初始化完的
    private static volatile Singleton3 singleton;

    private Singleton3() {
    }

    public static Singleton3 getInstance() {
        if (singleton == null) {
            synchronized (Singleton3.class) {
                if (singleton == null) {
                    singleton = new Singleton3();
                }
            }
        }
        return singleton;
    }
}

//如果单例需要延迟加载,又要线程安全且代码简洁
//使用内部类实现,在加载Singleton4时是不会加载InnerCls的,也就不会走new Singleton4()
// 只有调用getInstance()时用到了InnerCls才会被加载
public class Singleton4 {
    private Singleton4() {
    }

    public static Singleton4 getInstance() {
        return InnerCls.singleton;
    }

    private static class Inner {
        private static final Singleton4 singleton = new Singleton4();
    }
}

2、工厂

要生成如下产品:

 //抽象产品
public abstract class Product {
}

//具体产品A
public class ProductA extends Product {
}

//具体产品B
public class ProductB extends Product {
}

简单工厂模式

  • type方式传入,不符合开闭原则,新增要修改代码
public class SimpleCreator {
    public static <T extends Product> T createProduct(int type) {
        switch (type) {
            case 1:
                return new ProductA();
            break;
            case 2:
                return new ProductB();
            break;
        }
        return null;
    }
}
  • 使用反射 缺点:
  1. Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂。
  2. 不同的产品需要不同额外参数的时候 不支持。

public class SimpleCreator {
    public static <T extends Product> T createProduct(Class<T> c) {
        Product product = null;
        try {
            product = (Product) Class.forName(c.getName()).newInstance();
        } catch (Exception e) {
        }
        return (T) product;
    }
}
  • 多方法创建 有地方叫多方法工厂,java.util.concurrent.Executors使用
    优点方便创建 同种类型的 复杂参数的对象
    缺点 不符合开闭
public class SimpleCreator {
    public static <T extends Product> T createProductA() {
        return new ProductA();
    }

    public static <T extends Product> T createProductB() {
        return new ProductB();
    }
}

工厂方法模式

普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。(一般->特殊)

//抽象工厂类
public abstract class Creator {
    public abstract <T extends Product> T createProduct(Class<T> c);
}

//具体工厂类
public class ProductCreator extends Creator {
    @Override
    public <T extends Product> T createProduct(Class<T> c) {
        Product product = null;
        try {
            product = (Product) Class.forName(c.getName()).newInstance();
        } catch (Exception e) {
        }
        return (T) product;
    }
}
//或不使用反射,根据字符串内部判断生成的类,为每个产品创建一个工厂,也能达到开闭原则,但是类会变多
public abstract class Creator {
    public Product createProduct();
}

//具体工厂类
public class ProductACreator extends Creator {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

public class ProductBCreator extends Creator {
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}

抽象工厂模式

abstract class Product 是一个产品大类(产品族),如果要在一个工厂中创建两个产品族(因为两个产品族有关系,如一辆车的左右门数量要一致),则需要使用抽象工厂模式

//另一个抽象产品族(礼物)
public abstract class Gift {
}

//礼物A
public class GiftA extends Gift {
}

//礼物B
public class GiftB extends Gift {
}

//抽象工厂类
public abstract class AbstractCreator {
    public abstract <T extends Product> T createProduct(Class<T> c);

    public abstract <T extends Gift> T createGift(Class<T> c);
    //若有多个产品族,则需要多个方法,违反开闭原则
}

//具体工厂类
public class ProductGiftCreator extends AbstractCreator {
    @Override
    public <T extends Product> T createProduct(Class<T> c) {
        Product product = null;
        try {
            product = (Product) Class.forName(c.getName()).newInstance();
        } catch (Exception e) {
        }
        return (T) product;
    }

    @Override
    public <T extends Gift> T createGift(Class<T> c) {
        Gift gift = null;
        try {
            gift = (Gift) Class.forName(c.getName()).newInstance();
        } catch (Exception e) {
        }
        return (T) gift;
    }
}

建造者模式

构造方法参数多,而且参数需要进一步处理
常用lombok 的@Builder 即可对一个实体类构建出建造者