单例模式
单例模式(Singleton Pattern) : 确保一个类只有一个实例(所以叫单例嘛), 而且自行实例化并向整个系统提供这个实例, 这个类称为单例, 它提供全局访问的方法.
同时它提供一个静态的getInstance()工厂方法, 让客户可以访问它的唯一实例.
因为需要防止外部对它进行实例化, 所以我们会将其构造函数设计为私有, 在单例类内部定义了一个Singleton类型的静态对象, 作为外部共享的唯一实例.
单例模式作用:
- 控制资源的使用, 通过线程同步来控制资源的并发访问
- 控制实例产生的数量, 达到节约资源的目的
- 它可以在不建立直接关联的条件下, 让多个不相关的两个线程或者进程之间实现通信(作为通信媒介)
单例模式应用场景:
- 一般池的设计都是单例模式, 例如数据库连接池和多线程的连接池, 这样会方便对池中的连接/线程进行控制, 降低资源的消耗.
- 网站的计数器一般也是采用单例模式
- Windows系统的任务管理器和回收站都是使用单例模式
手撸单例模式
懒汉式线程不安全
package baguwen;
public class Singleton {
//生成唯一的实例
private static Singleton singleton;
//用private修饰构造方法, 让外部无法对其实例化
private Singleton() {
}
private static Singleton getSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
懒汉式线程安全
package baguwen;
public class Singleton {
//生成唯一的实例
private static Singleton singleton;
//用private修饰构造方法, 让外部无法对其实例化
private Singleton() {
}
//使用synchronized修饰符修饰方法对其上锁, 使其线程安全
private static synchronized Singleton getSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
饿汉式
package baguwen;
public class Singleton {
//最大的区别, 开局就new一个对象出来
private static Singleton singleton = new Singleton();
private Singleton() {
}
private static Singleton getSingleton() {
return singleton;
}
}
工厂模式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
简单工厂模式
一个抽象产品类, 具体产品类, 一个工厂
工厂是一个简单的类, 其中生成返回具体产品通常使用if-else或者switch-case
返回产品的方法一般都是static, 所以也称之为静态工厂方法模式
优点 :
-
简单易于实现
-
把类的实例化交给工厂, 易于解耦
开放封闭原则: 软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化, 而不是通过修改已有的代码来实现变化。
缺点 :
- 添加具体产品需要修改工厂违反OCP开放封闭原则
手撸简单工厂模式:
先来一个手机接口
package factory;
public interface Phone {
void make();
}
之后来实现这个接口造个小米
package factory;
public class XiaoMi implements Phone {
@Override
public void make() {
System.out.println("Are U Okay? XiaoMi 10Pro Yes!");
}
public XiaoMi() {
this.make();
}
}
再整个IPhone
package factory;
public class IPhone implements Phone{
@Override
public void make() {
System.out.println("IPhone4S, the best smartPhone in the world");
}
public IPhone() {
this.make();
}
}
最关键的造一个PhoneFactory(让它来帮我们实例化对象
package factory;
public class PhoneFactory {
public static Phone makePhone(String phoneType) {
if (phoneType.equals("XiaoMi")) {
return new XiaoMi();
}else if (phoneType.equals("IPhone")) {
return new IPhone();
}
return null;
}
}
来测试一下!
package factory;
public class Test {
public static void main(String[] args) {
PhoneFactory phoneFactory = new PhoneFactory();
Phone xiaomi = phoneFactory.makePhone("XiaoMi");
Phone iphone = phoneFactory.makePhone("IPhone");
}
}
有一说一小米10p确实很香
工厂方法模式
一个抽象产品类, 多个具体产品类, 一个抽象工厂, 多个具体工厂
定义一个用来创建对象的接口, 但让子类决定实例化哪一个类, 工厂方法把实例化的权利交给了子类
优点:
- 易于扩展,降低了代码耦合度, 对象的生成交给子类去完成
- 实现了开放封闭原则, 每次添加子产品不需要修改原有代码
缺点 :
- 增加了代码量, 毕竟每一个具体产品都需要一个具体工厂
- 增加抽象产品的时候需要修改工厂, 违背了OCP开放封闭原则
手撸工厂方法模式
AbstractFactory接口, 用于生产不同产品的工厂的抽象类
package abstractFactory;
import factory.Phone;
public interface AbstractFactory {
Phone makePhone();
}
苹果工厂(富士康(x
package abstractFactory;
import factory.IPhone;
import factory.Phone;
public class AppleFactory implements AbstractFactory{
@Override
public Phone makePhone() {
return new IPhone();
}
}
小米加工厂是哪个来着…不会是那位大人的吧(x
package abstractFactory;
import factory.Phone;
import factory.XiaoMi;
public class XiaoMiFactory implements AbstractFactory {
@Override
public Phone makePhone() {
return new XiaoMi();
}
}
测试一手!
package abstractFactory;
public class Demo {
public static void main(String[] args) {
XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();
AppleFactory appleFactory = new AppleFactory();
xiaoMiFactory.makePhone();
appleFactory.makePhone();
}
}
RuN!
抽象工厂模式
上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品, 如果要生成另一类产品那应该如何表示?
这时候我们就需要用到抽象工厂模式
手撸一下吧! 定义一下PC接口
package abstractFactory;
public interface PC {
void make();
}
增加MAC和xiaomiPC
package abstractFactory;
public class XiaoMiPC implements PC{
@Override
public void make() {
System.out.println("小米PC, 就这就这就这??");
}
public XiaoMiPC() {
this.make();
}
}
package abstractFactory;
public class MAC implements PC{
@Override
public void make() {
System.out.println("MAC, YYDS!");
}
public MAC() {
this.make();
}
}
修改一下工厂接口
package abstractFactory;
import factory.Phone;
public interface AbstractFactory {
Phone makePhone();
PC makePC();
}
修改一下工厂(添加makePc方法
package abstractFactory;
import factory.IPhone;
import factory.Phone;
public class AppleFactory implements AbstractFactory{
@Override
public Phone makePhone() {
return new IPhone();
}
@Override
public PC makePC() {
return new MAC();
}
}
package abstractFactory;
import factory.Phone;
import factory.XiaoMi;
public class XiaoMiFactory implements AbstractFactory {
@Override
public Phone makePhone() {
return new XiaoMi();
}
@Override
public PC makePC() {
return new XiaoMiPC();
}
}
总结
简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。
工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
抽象工厂模式是工厂方法模式的升级版,后者面向单个产品,而前者面向的的是一个产品族。根据官方定义:为创建一组相关/互相依赖的对象提供一个接口而无需指定它们的具体类。
比如一个汽车工厂要生成骑车,而每种汽车都有车门、车轮胎等一系列产品,这意味着每增加一款汽车就需要增加一个新的工厂来提供新产品的实现。这时候就可以使用抽象工厂模式来进行设计。抽象工厂模式适用于一系列产品族。