设计模式遵循的原则有6个:
- 开闭原则(Open Close Principle) 对扩展开放,对修改关闭。
- 里氏代换原则(Liskov Substitution Principle) 只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真 正被复用,而衍生类也能够在基类的基础上增加新的行为。
- 依赖倒转原则(Dependence Inversion Principle) 这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。
- 接口隔离原则(Interface Segregation Principle) 使用多个隔离的借口来降低耦合度。
- 迪米特法则(最少知道原则)(Demeter Principle) 一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相 对独立。
- 合成复用原则(Composite Reuse Principle) 原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类 的封装性,超类的方法可能会被子类修改。
单例模式
定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
- 构造方法必须是私有的,防止被外部实例
- 一个类只有一个实例,属于这个类,所以这个实例应该是这个类的成员变量,静态变量
懒汉式
在第一次使用的时候进行类加载。
/**
* 懒汉式单例模式(双重校验的、线程安全的)
*
* @Author guoXin Sun
* @Date 2022/3/9 15:14
* @Version 1.0
*/
public class LazySingleton {
//持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载
private static LazySingleton instance = null;
/* 私有构造方法,防止被实例化 */
private LazySingleton() {
}
/* 1:懒汉式,静态工程方法,创建实例 */
public static LazySingleton getInstance() {
if (instance == null) {
//线程安全
synchronized (LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}
饿汉式
在类加载的时候就进行实例化
使用场景:
- 要求生成唯一序列号的环境;
- 在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;
- 创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源;
- 需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式 (当然,也可以直接声明为static的方式)。
/**
* 饿汉式单例
* @Author guoXin Sun
* @Date 2022/3/9 15:14
* @Version 1.0
*/
public class HurrySingleton {
private volatile static HurrySingleton instance = new HurrySingleton();
/* 私有构造方法,防止被实例化 */
private HurrySingleton() {
}
// 创建实例,并返回
public static HurrySingleton getInstance() {
return instance;
}
}
代理模式
为其他对象提供一种代理以控制对这个对象的访问
使用场景:网络连接的建立、IO流的建立、日志
public class Proxy {
public static void main(String[] args) {
SubjectProxy subjectProxy = new SubjectProxy(new RealSubject());
subjectProxy.doSome();
}
}
interface Subject {
void doSome();
}
/**
* 目标类
*/
class RealSubject implements Subject {
@Override
public void doSome() {
}
}
/**
* 静态代理类
*/
class SubjectProxy implements Subject {
private RealSubject subject;
public SubjectProxy(RealSubject subject) {
this.subject = subject;
}
@Override
public void doSome() {
System.out.println("执行前");
System.out.println("执行中");
System.out.println("执行后");
}
}
工厂模式
- 我们最常用的 Spring 就是一个最大的 Bean 工厂,IOC 通过
FactoryBean
对Bean 进行管理。 - 我们使用的日志门面框架
slf4j
,点进去就可以看到熟悉的味道
简单工厂模式
简单工厂模式,它属于类创建型模式,在简单工厂模式中,可以根据参数的不同返回不同类的实例。
专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
三个角色:工厂类、抽象类产品、具体产品
优点:将对象的创建和使用彻底分离
缺点:不够灵活,如果新增产品就需要修改工厂类源码
/**
* 简单工厂模式
* @Author guoXin Sun
* @Date 2022/3/9 17:37
* @Version 1.0
*/
public class SimpleFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) {
return new ProductA();
}
return new ProductB();
}
public static void main(String[] args) {
Product a = createProduct("B");
a.print();
}
}
/**
* 共同父类抽象类
*/
abstract class Product {
public abstract void print();
}
/**
* 产品A
*/
class ProductA extends Product {
@Override
public void print() {
System.out.println("产品A被创建");
}
}
/**
* 产品B
*/
class ProductB extends Product {
@Override
public void print() {
System.out.println("产品B被创建");
}
}
工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
生产哪个对象不再由参数决定,而是创建工厂时,调用工厂的方法创建。
四个角色:产品抽象类、产品类、工厂接口、工厂实现类
完全符合开闭原则
使用:数据库访问、记录日志
优点:扩展性高
缺点:每次增加产品都需要新建工厂类和实现的工厂。
/**
* 工厂模式
* @Author guoXin Sun
* @Date 2022/3/9 18:11
* @Version 1.0
*/
public class Factory {
public static void main(String[] args) {
FactoryA factoryA = new FactoryA();
factoryA.createFactory().print();
}
}
/**
* 抽象的工厂接口
*/
interface AbstractFactory{
Fruit createFactory();
}
class FactoryA implements AbstractFactory {
@Override
public Fruit createFactory() {
return new Apple();
}
}
class FactoryB implements AbstractFactory {
@Override
public Fruit createFactory() {
return new Orange();
}
}
/**
* 抽象产品
*/
abstract class Fruit {
public abstract void print();
}
/**
* 产品A
*/
class Apple extends Fruit {
@Override
public void print() {
System.out.println("生产一个苹果");
}
}
/**
* 产品B
*/
class Orange extends Fruit {
@Override
public void print() {
System.out.println("生产一个橘子");
}
}
抽象工厂模式
因为工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。所以我们可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产
产品族是指位于不同产品等级结构中功能相关联的产品组成的家族。
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须指 定它们的具体类。
五个角色:抽象工厂、具体工厂、抽象产品、具体产品
/**
* @Author guoXin Sun
* @Date 2022/3/9 20:16
* @Version 1.0
*/
public class AbstractFactory {
public static void main(String[] args) {
Shape shape = new FactoryRedShape1().getShape();
shape.print();
Shape shape1 = new FactoryBlueShape1().getShape();
shape1.print();
}
}
/**
* 抽象产品接口
*/
interface Shape {
void print();
}
/**
* 抽象实现接口
*/
abstract class Shape1 implements Shape {
public abstract void print();
}
abstract class Shape2 implements Shape {
public abstract void print();
}
/**
* 具体实现类
*/
class RedShape1 extends Shape1{
@Override
public void print() {
System.out.println("红色的形状1");
}
}
class BlueShape1 extends Shape2{
@Override
public void print() {
System.out.println("蓝色的形状2");
}
}
/**
* 抽象工厂
*/
interface ShapeFactory {
Shape getShape();
}
/**
* 具体工厂
*/
class FactoryRedShape1 implements ShapeFactory {
@Override
public Shape getShape() {
return new RedShape1();
}
}
class FactoryBlueShape1 implements ShapeFactory {
@Override
public Shape getShape() {
return new BlueShape1();
}
}