Java中23种设计模式精讲

设计模式六大原则

  • 单一原则(Single Responsibility Principle):一个类或者一个方法只负责一项职责,尽量做到类的只有一个行为原因引起变化;
      a、业务对象(BO business object)、业务逻辑(BL business logic)拆分;
  • 里氏替换原则(LSP liskov substitution principle):子类可以扩展父类的功能,但不能改变原有父类的功能;(本质其实就是c++的多态)
      (目的:增强程序的健壮性)实际项目中,每个子类对应不同的业务含义,使父类作为参数,传递不同的子类完成不同的业务逻辑。
  • 依赖倒置原则(dependence inversion principle):面向接口编程;(通过接口作为参数实现应用场景)
      抽象就是接口或者抽象类,细节就是实现类
      含义:
        上层模块不应该依赖下层模块,两者应依赖其抽象;
        抽象不应该依赖细节,细节应该依赖抽象;

    通俗点就是说变量或者传参数,尽量使用抽象类,或者接口;
    【接口负责定义public属性和方法,并且申明与其他对象依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑】
    注:可以通过setter方式或者构造器方法注入
  • 接口隔离(interface segregation principle):建立单一接口;(扩展为类也是一种接口,一切皆接口)
       定义:
        a.客户端不应该依赖它不需要的接口;
        b.类之间依赖关系应该建立在最小的接口上;
    简单理解:复杂的接口,根据业务拆分成多个简单接口;(对于有些业务的拆分多看看适配器的应用)
     【接口的设计粒度越小,系统越灵活,但是灵活的同时结构复杂性提高,开发难度也会变大,维护性降低】
  • 迪米特原则(law of demeter LOD):最少知道原则,尽量降低类与类之间的耦合;
    一个对象应该对其他对象有最少的了解
  • 开闭原则(open closed principle):用抽象构建架构,用实现扩展原则;(总纲)

1.单例模式

  • 单例模式,属于创建类型的一种常用的软件设计模式。单例模式保证了 系统内存中该类只存在一个实例,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
  • 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new
  • 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session 工厂等)
  • jdk中应用场景:java.long.Runtime

饿汉式

// 1.私有构造方法,其它类不能访问该构造方法
    private Singleton1() {
    
     }
    // 2.创建本类对象,且让它私有,目的是不让其修改该对象
    private static Singleton1 singleton1 = new Singleton1();
    // 3.对外提供公共的访问方法 获取实例
    public static Singleton1 getInstance() {
    
    
        return singleton1;
    }
}

懒汉式

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

双重检验锁(推荐!效率和线程安全都很好)

DCL模式的优点就是,只有在对象需要被使用时才创建,第一次判断 INSTANCE == null为了避免非必要加锁,当第一次加载时才对实例进行加锁再实例化。这样既可以节约内存空间,又可以保证线程安全

class Singleton2 {
    
    
    // 私有化构造方法,防止通过new的方式创建对象
    private Singleton(){
    
    }
    private volatile static Singleton singleton;//volatile保证不会指令重排,可见的话new的三步操作对所有线程都可见,不会因为只看见两步而判断失误

    public static Singleton getInstance() {
    
    
        if (singleton == null) {
    
    
            synchronized (Singleton.class) {
    
    //synchronized 保证原子性
                if (singleton == null) {
    
    
                    singleton = new Singleton();//new有三个操作,不是原子性。分配内存空间;初始化对象;将对象指向内存三步
                }
            }
        }
        return singleton;
    }

静态内部类(推荐!效率和线程安全都很好)

外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。即当SingleTon第一次被加载时,并不需要去加载SingleTonHoler,只有当getInstance()方法第一次被调用时,才会去初始化INSTANCE,第一次调用getInstance()方法会导致虚拟机加载SingleTonHoler类,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。

class Singleton {
    
    
    private static volatile Singleton instance;

    //构造器私有化private Singleton() {}
    private Singleton() {
    
    
    }

    //写一个静态内部类,该类中有一个静态属性 Singleton private static class SingletonInstance {
    
    
    private static class SingletonInstance {
    
    
        private static final Singleton INSTANCE = new Singleton();
    }

    //提供一个静态的公有方法,直接返回 SingletonInstance.INSTANCE public static synchronized Singleton getInstance() {
    
    
    public static Singleton getInstance() {
    
    
        return SingletonInstance.INSTANCE;
    }
}

2.简单工厂模式

简单工厂模式又称为静态工厂方法,它属于类创建模型。在简单工厂模式中,可根据参数的不同而返回不同类的实例。简单工厂模式专门定义一个类负责创建其它类的实例,被创建的实例通常有共同的父类。

public class SimpleFactory {
    
    
    public static Product createProduct(String type) {
    
    
        if (type.equals("a"))
            return new ProductA();
        else
            return new ProductB();
    }

    public static void main(String[] args) {
    
    
        Product product = SimpleFactory.createProduct("a");
        product.print();
    }
}
//抽象类不能实例化对象,必须由它的子类完成
abstract class Product {
    
    
    public abstract void print();
}

class ProductA extends Product {
    
    
    @Override
    public void print() {
    
    
        System.out.println("a");
    }
}

class ProductB extends Product {
    
    
    @Override
    public void print() {
    
    
    }
}

3.工厂模式

工厂模式是把简单工厂时的统一创建实例变为了分给具体的工厂的去创建,如下图,但创建的实例都是属于同一大类。
在这里插入图片描述

4.抽象工厂模式

在工厂模式的基础上,增加其它大类的产品。
在这里插入图片描述

4.装饰器模式

动态的给一些对象添加一些功能
原先的对象为new FirstRobot()只会”对话,唱歌”,当我们把这个最初的对象传入装饰器RobotDecorator中时,原先对象不仅可以使用自己最初的对话唱歌,还可以使用它的额外方法,跳舞拖地。

class DecoratorPattern {
    
    
    public static void main(String[] args) {
    
    
        new RobotDecorator(new FirstRobot()).doMorething();
    }
}

interface Robot {
    
    
    void doSomething();
}

class FirstRobot implements Robot {
    
    
    public void doSomething() {
    
    
        System.out.println("对话");
        System.out.println("唱歌");
    }
}

class RobotDecorator implements Robot {
    
    
    private Robot robot;

    public RobotDecorator(Robot robot) {
    
    
        this.robot = robot;
    }

    public void doSomething() {
    
    
        robot.doSomething();
    }
    public void doMorething() {
    
    
        robot.doSomething();
        System.out.println("跳舞,拖地");
    }
}

5.原型模型

原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节

原型模式通常适用于以下场景。
对象之间相同或相似,即只是个别的几个属性不同的时候。
对象的创建过程比较麻烦,但复制比较简单的时候。

5.适配器模型

class AdapterPattern {
    
    
    public static void main(String[] args) {
    
    
        new Adapter(new Speaker()).translate();
    }
}

class Speaker {
    
    
    public String speak() {
    
    
        System.out.println("China No.1");
        return null;
    }
}

interface Translator {
    
    
    public String translate();
}

class Adapter implements Translator {
    
    
    private Speaker speaker;

    public Adapter(Speaker speaker) {
    
    
        this.speaker = speaker;
    }

    public String translate() {
    
    
        String result = speaker.speak();
        return result;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40485391/article/details/107740457