Java设计模式

前言:设计模式简述

设计模式是一种编程思想,它实际就是面向对象思想的实际运用。它体现了复用性、低耦合性、高扩张性等等面向对象的思想,能大大提高我们的项目质量。

总共有23种设计模式,这些模型在大多时候是混合在一起使用的,它们各自有优点和缺点,应结合实际正确使用。

  • 创建型模式
    单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式

  • 结构式模式
    设配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式

  • 行为型模式
    模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、访问者模式、职责链模式


创建者模式

单例模式

顾名思义,单例模式就是一个类在整个运行时期,只有一个实例对象。为什么会出现单例模式呢?比如对于某些类,它的创建和销毁过程过于复杂,且它可以复用,如果对它进行频繁的创建和销毁,就会浪费大量资源。所以单例模式应运而生。

  • 优点:可以节省不必要浪费的资源
  • 特点
    1. 类在整个运行期间都只有一个实例
    2. 构造器私有,有公开的构造实例的静态方法
    3. 有一个静态的类实例对象,表示唯一存在的实例对象

下面来看代码,单例模式有两种实现方式,分别是饿汉式懒汉式

饿汉式
public class Test {
    private Test() {
    }

    private static final Test test = new Test();

    public static Test getInstance(){
        return test;
    }
}
懒汉式
public class Test {
    private Test() {
    }

    private static Test test;

    public static Test getInstance(){
        if(test == null){
            test = new Test();
        }
        return test;
    }
}

顾名思义,饿汉式就是加载的时候就去创建实例对象,懒汉式就是在第一次使用的时候再去创建实例对象,毫无疑问,肯定是懒汉式比较优秀。不过懒汉式也有缺点,就是它是线程不安全的。

懒汉式不是线程安全的,那怎么解决呢?加锁嘛,我们可以用synchronized锁住就好。但是如果直接在getInstance()方法上加锁又对性能影响过大,所以我们可以考虑一下方法。

public class Test {
    private Test() {
    }

    private static Test test;

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

如上面,使用类锁便可解决,但真的解决了吗?并没有,这个代码还是有问题的,因为假如已经有多个线程进入if语句里,就会造成创建多个实例对象,从而破坏了单例模式,所以需要再加一个判断,也就是我们的双重检测锁模式的懒汉式,也叫DLC懒汉式。

public class Test {
    private Test() {
    }

    private static Test test;

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

还没完,如果你对多线程熟悉,你会发现test = new Test();这一步并不是原子操作,它分为3步操作,所以可能会出现指令重排,造成错误,所以应该将test对象使用volatile修饰。所以完整的懒加载且线程安全的写法如下:

public class Test {
    private Test() {
    }

    private static volatile Test test;

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

但是但是,还是没完,以上的写法其实都是可以通过反射来破坏单例模式的,对此我们也有对策,就是采用枚举类型,枚举类型是无法通过反射来破坏的,它会报出异常。但是枚举类型又不能用于懒汉式,它的原理和饿汉式相同,类加载的时候就已经构建好实例对象了。

所以当前暂时没有同时满足懒汉式、线程安全、反射不能破坏的写法,只能满足其中的两种,这就是单例模式,如果有兴趣也可以看下以下两个视频:

https://www.bilibili.com/video/BV1pt4y1X7kt?from=search&seid=16397970082293022209
https://www.bilibili.com/video/BV1K54y197iS?from=search&seid=16397970082293022209

工厂模式

还是先说说为什么要有工厂模式吧。工厂模式是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只是调用B的方法,而至于B的实例化,就交给工厂类。

其次,工厂模式可以降低代码重复。如果创建对象B的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。我们可以这些创建对象B的代码放到工厂里统一管理。既减少了重复代码,也方便以后对B的创建过程的修改维护。

同理由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。

下面有一篇博客,个人觉得写得很不错,对于了解工厂模式的作用有很大帮助:

https://blog.csdn.net/kocscs123/article/details/53243847?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159594280519724811852397%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159594280519724811852397&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v3~pc_rank_v2-1-53243847.first_rank_ecpm_v3_pc_rank_v2&utm_term=%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F%E4%BD%9C%E7%94%A8&spm=1018.2118.3001.4187

工厂模式分为两种:简单工厂模式和工厂方法模式,它们的核心本质就是实例化对象不直接new出来,而是使用工厂方法创建,正如我们熟知的一些类有Factory,如线程池。这样实现了创建者和调用者的分离。

  • 优点:降低了耦合度,使创建者和使用者分离
  • 分类
    • 简单工厂模式:用来生产同一等级结构中的任意产品,代码量较小,但增加新产品需要修改已有代码
    • 工厂方法模式:用来生产同一等级结构中的固定产品,代码量较大,但支持增加新产品,只需在原有基础上扩展即可

下面举例来演示下这两种方法,用买车的例子。假如有两种车,分别为AB种,它们实现了car这个接口,现在有用户来买车:

简单工厂模式

在这里插入图片描述

public interface Car {
    void name();
}

class A implements Car{
    @Override
    public void name() {
        System.out.println("A种车");
    }
}

class B implements Car{
    @Override
    public void name() {
        System.out.println("B种车");
    }
}

class Factory{
    public static A getA(){
        return new A();
    }

    public static B getB(){
        return new B();
    }
}

class  Customer{
    public static void main(String[] args) {
        //不直接new对象,而是通过工厂创建实例对象
        A a = Factory.getA();
        a.name();
        B b = Factory.getB();
        b.name();
    }
}

上面便是简单工厂模式实现,但是如果我们新增一种车,则必定要改动工厂的代码,不符合我们的面向对象思想。下面我们来看下工厂方法模式:

工厂方法模式

在这里插入图片描述

public interface Car {
    void name();
}

class A implements Car{
    @Override
    public void name() {
        System.out.println("A种车");
    }
}

class B implements Car{
    @Override
    public void name() {
        System.out.println("B种车");
    }
}

interface CarFactory{
     Car getInstance();
}

class ACarFactory implements CarFactory{

    @Override
    public Car getInstance() {
        return new A();
    }
}

class BCarFactory implements CarFactory{
    @Override
    public Car getInstance() {
        return new B();
    }
}

class  Customer{
    public static void main(String[] args) {
        //不直接new对象,而是通过工厂创建实例对象
        A a = (A)new ACarFactory().getInstance();
        a.name();
        B b = (B)new BCarFactory().getInstance();
        b.name();
    }
}

从上面我们可以很清楚的看到,如果我们有了一种新的车,我们只需要新建一个新的工厂然后实现工厂接口就可以了,且各种车的工厂是独立的,我们也可以在各种车工厂里提供特有方法,但是弊端也很明显,就是代码量大大增加,每多一种车就要多出一个工厂。所以我们要根据实际情况决定。

抽象工厂模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值