> 文章列表 > java设计模式(2)单例模式、工厂模式、建造者模式

java设计模式(2)单例模式、工厂模式、建造者模式

java设计模式(2)单例模式、工厂模式、建造者模式

单例模式

单例对象的类必须保证只有一个实例存在

饿汉式单例

饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的

//饿汉式单例类.
public class Singleton {//构造器私有化private Singleton() {}//static修饰 在类初始化时,已经自行实例化private static final Singleton single = new Singleton();//静态工厂方法 public static Singleton getInstance() {return single;}
}
  • 优点:保证线程绝对安全
  • 缺点:所有对象类加载的时候就实例化,系统初始化就会导致大量的内存浪费

懒汉式单例

//懒汉式单例类
public class Singleton {//构造器私有化private Singleton() {}private static Singleton single = null;//静态工厂方法 public static Singleton getInstance() {if(single==null){//在第一次调用的时候实例化自己 single=new Singleton();}return single;}
}

优点:解决了饿汉式单例可能带来的内存浪费问题,节省内存
缺点:线程不安全的问题

在多线程环境下,我们就要考虑到线程的安全问题:即是否有不同的线程分别new一个对象实例,导致不同线程创建的class类的实例不是同一个。


线程安全懒汉式

可以直接在方法加synchronized,但是不推荐。会导致资源浪费

//懒汉式-线程安全
public class Singleton {//构造器私有化private Singleton() {}private static volatile Singleton single = null;//静态工厂方法public static synchronized Singleton getInstance() {if (single != null) {return single;}single = new Singleton()return single;}
}

懒汉式双重锁

双重锁检查:方法检查判定两次,并使用锁,所以形象称为双重检查锁定模式。

1.首先判断变量是否被初始化,没有被初始化,再去获取锁。

2.获取锁之后,再次判断变量是否被初始化。第二次判断目的在于有可能其他线程获取过锁,已经初始化改变量。第二次检查还未通过,才会真正初始化变量。

用 volatile定义的变量,将会保证对所有线程的可见性。禁止指令重排序优化。

//懒汉式-线程安全
public class Singleton {//构造器私有化private Singleton() {}private static volatile Singleton single = null;//静态工厂方法public static Singleton getInstance() {if (single != null) {return single;}synchronized (Singleton.class) {if (single == null) {//在第一次调用的时候实例化自己single = new Singleton();}}return single;}
}

工厂模式

准备工作

public interface Phone {//规范:每个手机都只能玩游戏void play();
}

oppo手机

public class OPPO implements Phone{@Overridepublic void play() {System.out.println("使用oppo手机 play games");}
}

vivo手机

public class VIVO implements Phone{@Overridepublic void play() {System.out.println("使用vivo手机 play games");}
}

小米手机

public class XiaoMi implements Phone {@Overridepublic void play() {System.out.println("使用xiaomi手机 play games");}
}

简单工厂模式

简单工厂模式:创建一个工厂类根据传入的参数决定创建出哪一种产品的实例

//简单工厂模式
public class PhoneFactory {public static Phone getPhone(String phone) {//通过给工厂传入不同的参数,拿到不一样的手机if (phone.equals("oppo")) {return new OPPO();} else if (phone.equals("vivo")) {return new VIVO();} else if (phone.equals("xiaomi")) {return new XiaoMi();} else {return null;}}
}

测试:

 public static void main(String[] args) {Phone phone = PhoneFactory.getPhone("xiaomi");phone.play();}


工厂方法模式

此时每一种品牌都有自己的工厂制作自己品牌的手机。定义一个工厂接口基类,

public interface PhoneFactory {//定义创建产品的抽象方法Phone makePhone();
}

oppo工厂

//oppo工厂
public class OPPOFactory implements PhoneFactory {@Overridepublic Phone makePhone() {return new OPPO();}
}

vivo工厂

//vivo工厂
public class VIVOFactory implements PhoneFactory{@Overridepublic Phone makePhone() {return new VIVO();}
}

小米工厂

//小米工厂
public class XiaoMiFactory implements PhoneFactory {@Overridepublic Phone makePhone() {return null;}
}

测试

public static void main(String[] args) {OPPOFactory oppoFactory = new OPPOFactory();Phone phone = oppoFactory.makePhone();phone.play();
}

看的出来,我们新增了很多个工厂类,那么工厂方法模式好在哪里呢?

符合 开闭原则,在新增产品的时候不需要改动已经存在的代码,利于程序的扩展。而简单工厂模式在添加新的产品时,不得不修改工厂方法,扩展性不好。

工厂方法模式缺点:就是在新增产品的时候需要新增产品类和工厂类(成对增加)。


抽象工厂模式

与工厂方法模式相比,抽象工厂模式中的工厂不再只是创建一种具体的产品(比如上面,我们的小米工厂就只是去创建小米手机)。

抽象工厂模式的工厂创建一组产品。这一组产品式一系列相关相互依赖对象。比如小米工厂创建的小米手机、小米手环、小米电视、小米充电宝、小米电脑....

简单整一个统一的电视接口

public interface TV {void watchTV();
}

小米电视

public class XiaoMITV implements TV {@Overridepublic void watchTV() {System.out.println("使用小米电视 watch TV");}
}

抽象工厂Factory基类.。为了方便我就只写了俩个创建手机和创建电视。

//抽象工厂Factory基类
public interface Factory {Phone createPhone();TV createTV();
}

具体各个品牌的工厂类如下:为了方便我就只写了小米工厂手机和创建电视。

//小米工厂
public class XiaoMiFactory implements Factory {@Overridepublic Phone createPhone() {return new XiaoMi();}@Overridepublic TV createTV() {return new XiaoMITV();}
}

测试

public static void main(String[] args) {Factory factory = new XiaoMiFactory();Phone phone = factory.createPhone();phone.play();TV tv = factory.createTV();tv.watchTV();
}

抽象工厂模式优势:将具有一定共性的产品集合封装在一起。。更符合业务场景


建造者模式