Java设计模式总结

java · 浏览次数 : 15

小编点评

**110v** * 适配为既可以110v,也可以220v** **4:策略模式意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。** **5:策略模式意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。** **6:责任链模式** * 校验器接口 * Validator<T> * 责任链模式 * 校验器链上的每个校验器都判断对象是否符合要求,如果符合,则将对象传递到下一个校验器,直到对象符合所有要求为止。 * 最终,责任链上的最后一个校验器返回true,如果所有校验器都返回true,则对象符合所有要求。

正文

前言1

刚才整理博客的时候,发觉草稿箱里面躺了一篇文章。这篇文章来自于6年前,2018年,我还在读书的时候。当时csdn,博客园还是行业top,近些年掘金,思否,个人ip站的崛起,也预示着互联网进程的演变。

过了6年之久,这篇文章还没有发布,趁现在有空,补充并且发布一下。

前言2

面试的过程中多次提到设计模式,深感设计模式的重要性。在之前有看过秦小波老师写的《设计模式之禅》。 但当时仅限于看,包括现在也仅限于看。有的时候项目中,你都不知道有没有运用到了设计模式。也许用到了单例模式,但你并不知道如何用的,不知不觉就用到了。

  《武林外传》老白曾经说过这样一句话。高手就是手里无刀,心中也无刀。 类似于设计模式,你不知不觉中已经融进你的代码中了,但你并不知已经运用了。
下面我总结几个我觉得比较常用的设计模式。

1:设计模式分类

总体来说设计模式分为三大类:

创建型模式, 共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式, 共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式, 共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

大家没有必要死记硬背哪一种模式属于哪一种类型,面试如果问到,因为不会背而挂,只能说这家公司不去也罢。

我们需要真正理解,为什么工厂方法模式也是创建型模式,因为它是一个factory,他创建一个对象供你使用。又比如适配器模式为什么是结构型模式,它是不是从”顺序性编码“变成了”分支形编码“,改变了代码的结构。所以你需要真正理解每一种设计模式,做到不自觉的运用到你的代码中去。

2:单例模式

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

//懒汉 线程不安全
class SingletonDemo1 {

    private SingletonDemo1(){}

    private static SingletonDemo1 instance = null;

    public static SingletonDemo1 getInstance() {
        if (instance == null) {
            instance = new SingletonDemo1();
        }
        return instance;
    }
}

//懒汉 线程安全 直接加锁
class SingletonDemo2 {

    private SingletonDemo2() {}

    private static SingletonDemo2 instance = null;

    public static synchronized SingletonDemo2 getInstance() {
        if (instance == null) {
            instance = new SingletonDemo2();
        }
        return instance;
    }
}

// Double Check
public class SingletonDemo2 {
    private volatile static Singleton instance;

    private Singleton() {
    }

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


//饿汉 线程安全
class SingletonDemo3 {

    private SingletonDemo3() {}

    private static SingletonDemo3 instance = new SingletonDemo3();

    public static SingletonDemo3 getInstance() {
        return instance;
    }
}

//内部类 线程安全,并且懒加载
class SingletonDemo4 {

    private SingletonDemo4() {}

    private static class InnerSingletonDemo4 {
        private static final SingletonDemo4 instance = new SingletonDemo4();
    }

    public static final SingletonDemo4 getInstance() {
        return InnerSingletonDemo4.instance;
    }
}

// 枚举方式。最为推荐的一种方式
public enum SingletonDemo5 {
    INSTANCE;

    public void doSomeThing() {
    }
}

3: 适配器模式

举个例子,比较插头的电源为110v,但是我们现在想要220v的电源。所以我们就可以用适配器模式,使这个类符合我现有的要求。

同样,在编写JAVA程序时,我们可能会遇到这样一种情况:我们需要一个类A来实现接口B,但是类A并没有实现接口B中的所有方法,而类A是不能被改变的,这时我们可以创建一个类C,它继承类A并实现接口B,这个类C就是一个适配器。适配器中的代码将接受你所拥有的接口,并产生你所需要的接口。适配器模式有两张:类适配器模式和对象适配器模式。

// 假设这个规定电源为220v
interface A {

    void method220v();

}

//这个类实现的为110v的方法
class B {

    void method110v() {
        System.out.println("110v");
    }
}

// 适配为既可以110v,也可以220v
class C extends B implements A {

    @Override
    public void method220v() {

        System.out.println("220v");
    }
}

4:装饰着模式

装饰者模式通过组合的方式扩展对象的特性,这种方式允许我们在任何时候对对象的功能进行扩展甚至是运行时扩展,而若我们用继承来完成对类的扩展则只能在编译阶段实现,所以在某些时候装饰者模式比继承(inheritance)要更加灵活。

所谓装饰者,实际上就是将装饰的内容的以零部件的形式构建起来,然后经过组装形成一个一个新的逻辑内容,动态而灵活的组建逻辑性能。

// 形状
Shape circle = new Circle();

// 加了红色的形状
Shape redCircle = new RedShapeDecorator(new Circle());
  
// 加了红色的长方形
Shape redRectangle = new RedShapeDecorator(new Rectangle());

5:策略模式

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

应用实例:

  • 诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
  • 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
  • JAVA AWT 中的 LayoutManager。

优点:

  • 算法可以自由切换。
  • 避免使用多重条件判断。
  • 扩展性良好。

缺点:

  • 策略类会增多。
  • 所有策略类都需要对外暴露。

使用场景:

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  • 一个系统需要动态地在几种算法中选择一种。
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
举一个例子:
很简单的一个例子。比如人,人分为男人,女人,甚至不清楚性别的人。但这三种类型的人,都有不同的行为。那么我们在描述这些不同行为的时候,一般我们做法就是如下:

if (male) {
   //...
} else if (female) {
   //...
} else {
   //...
}

类似如上。很多个if,else进行嵌套。这样非常的难看,不优雅。如果我们用策略模式替换,会怎么样。

  • 第一步,定义一个Person类接口
  • 第二步定义person的继承类,如男人,女人等等
  • 第三步定义一个enum类,表示可选择性。
  • 最后一步定义一个策略选择器
public interface Person {
    void executeStrategy();
}

public class MalePerson implements Person {
    public void executeStrategy() {
        System.out.println("我是男性");
    }
}

public class FemalePerson implements Person {
    public void executeStrategy() {
        System.out.println("我是女性");
    }
}

public class UnknownPerson implements Person {
    public void executeStrategy() {
        System.out.println("未知性别");
    }
}


public enum SexEnum {
    MALE("male", "男性"),
    FEMALE("female", "女性"),
    UNKNOWN("unknown", "未知");

    private String code;
    private String sex;

    SexEnum(String code, String sex) {
        this.code = code;
        this.sex = sex;
    }
}

// 这块在实际开发中,我们会用factory结合spring来做这块逻辑
public class ContextStrategy {
    private MalePerson malePerson = new MalePerson();
    private FemalePerson femalePerson = new FemalePerson();
    private UnknownPerson unknownPerson = new UnknownPerson();

    public Person getPersonStrategy(SexEnum sexEnum) {
        if ("male".equals(sexEnum.getCode())) {
            return malePerson;
        } else if ("female".equals(sexEnum.getCode())) {
            return femalePerson;
        } else {
            return unknownPerson;
        }
    }
}


public class Main {
    public static void main(String[] args) {
        ContextStrategy strategy = new ContextStrategy();
        strategy.getPersonStrategy(**SexEnum.MALE**).executeStrategy();
        strategy.getPersonStrategy(**SexEnum.FEMALE**).executeStrategy();
        strategy.getPersonStrategy(**SexEnum.UNKNOWN**).executeStrategy();
    }
}

// 结果如下:
// 我是男性
// 我是女性
// 未知性别

其实我们可以看到。策略选择器是传入一个Enum类,然后根据传入Enum的不同,选择了不同的继承类。从而实现了if else。优雅的过渡。
可以看到,代码非常的优雅易懂,主代码,没有if else分支。但同时代码量多了起来。不过也很容易维护。

在实际项目中,我们一般会使用工厂模式 + 策略模式一起使用来达到减少if else的操作,策略模式在实际使用中非常的多,建议同学们务必掌握。

6:责任链模式

// 校验器接口
public interface Validator<T> {
    Validator<T> next();
    boolean handle(T t) throws FordealException;
}

public class BasicParameterValidator implements Validator<ValuationWO> {
    @Autowired
    private Validator<ValuationWO> tokenValidator;

    @Override
    public Validator<ValuationWO> next() {
        return tokenValidator;
    }

    @Override
    public boolean handle(ValuationWO valuationWO) throws Exception {
        return next().handle(valuationWO);
    }
}

最后

以上举了几个简单的例子,做一个抛砖引玉,还是希望同学们可以花一点时间,去了解下比较常用的设计模式。不需要背下来,多看看别人写的代码,然后尝试去模仿,慢慢的,你就会发觉,你就开始融会贯通了。做到手里无刀,心中也无刀,但实际上又快有准。

与Java设计模式总结相似的内容:

Java设计模式总结

前言1 刚才整理博客的时候,发觉草稿箱里面躺了一篇文章。这篇文章来自于6年前,2018年,我还在读书的时候。当时csdn,博客园还是行业top,近些年掘金,思否,个人ip站的崛起,也预示着互联网进程的演变。 过了6年之久,这篇文章还没有发布,趁现在有空,补充并且发布一下。 前言2 面试的过程中多次提

责任链和策略设计模式-基于Java编程语言

在日常代码的编写中,业务需求的变化总是不定的。文中描述的责任链和策略设计模式能有效满足代码编写的开闭原则,能更加有效的应对随时变化的业务需求。

限流器设计思路(浅入门)

目录令牌桶算法(Token Bucket)漏桶算法(Leaky Bucket)滑动窗口(Sliding Window)总结 限流器(Rate Limiter)是一种用于控制系统资源利用率和质量的重要机制。它通过限制单位时间内可以执行的操作数量,从而防止系统过载和保护服务的可靠性。在Java中,可以使

初步探索GraalVM——云原生时代JVM黑科技

1 云原生时代Java语言的困境 经过多年的演进,Java语言的功能和性能都在不断的发展和提高,诸如即时编译器、垃圾回收器等系统都能体现Java语言的优秀,但是想要享受这些功能带来的提升都需要一段时间的运行来达到最佳性能,总的来说Java是面向大规模、长时间使用的服务端应用而设计的。 云原生时代,J

(JAVA)设计模式-适配器模式

模式的定义和特点: 适配器模式(Adapter)是一种将一个类的接口转换成客户希望的另外一个接口的设计模式,可以提高代码的复用性和灵活性。 结构与实现: 定义一个适配器类来实现业务接口,再继承现有组件库中已经存在的组件。 示例: 创建业务接口类: 点击查看代码 public interface In

Netty-介绍-1

Netty介绍和应用场景 要求 已经掌握了 主要技术构成: Java OOP 编程、 Java 多线程编程、 Java IO 编程 、 Java 网络编程、 常用的Java 设计模式(比如 观察者模式 ,命令模式,职责链模式 )、 常用的数据结构(比如 链表) Netty的介绍 1、Netty 是由

Java面试题:你知道Spring的IOC吗?那么,它为什么这么重要呢?

Spring的IOC(控制反转)是一种设计模式,它允许开发者将对象的创建和管理交给Spring框架来完成。在Spring中,IOC允许开发者将对象依赖关系从代码中分离出来,从而使代码更加灵活、可重用和易于管理。 IoC 全称Inverse of Control(反向控制或控制反转)。 在类和类之间存

Java面试题:Spring框架除了IOC和AOP,还有哪些好玩的设计模式?

Spring是一个基于Java的企业级应用程序开发框架,它使用了多种设计模式来实现其各种特性和功能。本文将介绍一些在Spring中使用的常见设计模式以及相应的代码示例和说明。

Mybatis中的设计模式

最近在看《通用源码阅读指导书:Mybatis源码详解》,这本书一一介绍了Mybatis中的各个包的功能,同时也涉及讲了一些阅读源码的技巧,还讲了一些源码中涉及的设计模式,这是本篇文章介绍的内容 在多说一点这本书,Mybatis是大部分Java开发者都熟悉的一个框架,通过这本书去学习如何阅读源码非常合

7种创建方式,带你理解Java的单例模式

介绍创建Java单例对象的七种方式,重点掌握哪些创建方式是线程安全的,哪些方式是线程不安全的,并能够在实际项目中灵活运用设计模式,编写可维护的代码。