Java设计模式(七大原则和单例模式篇)

1. Java设计模式的概述

1.1 设计模式的目的及重要性

(1)软件工程中,设计模式是对软件设计中普遍的存在(反复出现)的各种问题,所提出的解决方案。

(2)代码重用性,可读性,可扩展性,可靠性,是程序呈现高内聚,低耦合的特性等。

1.2 设计模式的7大原则

1.2.1 单一职责原则

(1) 基本介绍:

a. 一个类应该专注于实现一个功能。

(2) 注意事项和原则:

a.即一个类只负责一项职责。
b.提高类的可读性,可维护性
c.降低变更引起的风险

1.2.2 接口隔离原则

(1) 基本介绍:

a.客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立
	在最小的接口上

1.2.3 依赖倒置原则

(1)基本介绍:

a.高层模块不应该依赖底层模块,两者都应该依赖其抽象
b.抽象不应该依赖细节,细节应该依赖抽象
c.依赖倒置的中心思想是面向接口编程
d.使用接口或者抽象类的目的是制定好规范,而不涉及任何具体的操作,
	把展现的细节交给他们的实现类去完成

(2) 依赖的传递方式:

a.接口传递
b.构造方式传递
c.setter方式传递

(3)依赖倒置的原则及注意事项

a.低级模块尽量都要有抽象类或者接口,或者两者都有,这样程序稳定性更好
b.变量的声明类型尽量是抽象类或接口,这样我们的变量引用和实例化对象间,
就存在一个缓冲区,利于程序扩展和优化
c.继承时遵守里氏替换原则

1.2.4 里氏替换原则

(1) 先说一下继承的思考和说明:

a.继承包含这样一层含义:父类中反是已经实现好的方法,实际上是设定
	规范和锲约,虽然它不强制要求所有的子类必须要遵守这些锲约,但是
	如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
	
b.继承再给程序带来遍历的时候,也同样带来了弊端,比如使用继承会
	给程序带来侵入性,程序的可移植性降低,增加对象的耦合性,如果
	一个类被其他类继承,则当这个类需要修改时,必须考虑到所有的子类,
	并且谷类修改后,所有涉及到的子类可能都会产生故障。

(2) 解决继承存在的方法:

a.通用做法就是:原来的父类和子类都继承一个更通俗的基类。原有的
	继承关系都去掉,采用依赖,聚合,组合等关系替代。

(3) 基本介绍:

a.所有引用基类的地方必须能透明的使用其子类的对象。

b.在使用继承时,遵守里氏替换原则,在子类中尽量不要重写父类的方法。

c.里氏替换原则告诉我们,继承其实让两个类的耦合性增强了,在适当的
	情况下,可以通过聚合,组合,依赖来解决问题。

1.2.5 开闭原则(OCP)

(1) 基本介绍:

1)开闭原则是编程中最基础,最重要的设计原则

2)一个软件实体,如类,模块和函数应该对外扩展开放,对修改关闭,
	用抽象构建框架,用实现扩展细节
	
3)放软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而
	不是通过修改已有的代码来实现变化。
	
4)编程中遵循其他原则,以及使用设计模式的目的就是遵循开闭原则

1.2.6 迪米特法则

(1) 基本介绍:

1)一个对象应该对其他对象保持最少的了解

2)类与类关系越亲密,耦合度越大

3)它又叫最少知道法则,即一个类对自己依赖的类知道的越少越好,
	也就是说,对于被依赖的类多复杂,都尽量将逻辑封装在类的内
	部,对外除了提供的public方法,不对外泄露任何信息
	
4)只与直接的朋友通信

5)直接的朋友:每个对象都会与其他对像由耦合度关系,只要两个
	对象之间有耦合度关系,我们就说这两个对象是朋友关系。耦
	合的方式很多,依赖,关联,组合,聚合等。其中,我们称出
	现成员变量,方法参数,方法返回值中的类为直接的朋友。而
	出现在局部变量中的类不是直接的朋友,也就是说,陌生的类
	最好不要以局部变量的形式出现在类的内部。

(2) 迪米特法则的注意事项和细节:

1)迪米特法则是降低类之间的耦合

2)注意:由于每个类都是减少了不必要的依赖,因此迪米特法则只是要
	求降低类之间的耦合关系,并不是要求完全没有依赖

1.2.7 合成复用原则

(1) 基本介绍:

1)原则是尽量使用合成/聚合的方式,而不是继承的方式。

1.3 设计原则核心思想

(1) 找出应用中可能需要变化之处,把他们独立出来。不要和那些不需要变化的代码混在一起。

(2) 针对接口编程,而不是针对实现编程

(3) 为了交互对象之间的松耦合设计而努力

2. 设计模式3的种类型(23种模式)

2.1创建型模式

(1)创建型模式:

单例模式 抽象工厂模式 原型模式 建造者模式 工厂模式。

2.2 结构型模式

(1)结构型模式:

适配器模式 桥接模式 装饰模式 组合模式 外观模式 享元模式 代理模式

2.3 行为型模式

(1)行为型模式:

(3)模板方式模式 命令模式 访问者模式 迭代器模式 观察者模式 
	中介者模式 备忘录模式 解释器模式 状态模式 策略模式 责任链模式

3. 模式的秘密开始

3.1 单例模式(一共八种)

3.1.1饿汉模式(静态变量):

(1)优缺点:

a.优点:这种写法简单,就是在类装载的时候就完成实例化,避免
	了线程同步问题。

b.缺点:在类装载的时候就完成实例化,没有达到lazy loading的
	效果,如果从始至终都没有使用过这个实例的话,就造成了不必要的浪费

c.这种方法基于classloder机制避免了多线程的同步问题,不过,
	instance在类装载的时候就初始化实例,在单例模式中大多数
	都是调用getInstance方法。但是导致类装载的原因有和多种,
	因此不能确定有其他方法导致类装载,这时候初始化instance
	就没有达到lazy loading的效果

d.结论:这种单例模式可用,但是可能造成内存浪费

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 饿汉式之静态变量 {
    public static void main(String[] args) {
        // 测试
        Singleton instance = Singleton.getInstance();
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance == instance1);  // true
        System.out.println(instance.hashCode() == instance1.hashCode()); // true
    }
}

class Singleton{
    // 1.构造器私有化,外部不能new
    private Singleton(){

    }
    // 2.本类内部创建实例
    private final static Singleton singLeton = new Singleton();

    // 3.对外提供一个公共的静态方法 返回实例对象
    public static Singleton getInstance(){
        return singLeton;

    }
}

3.1.2饿汉模式(静态代码块):

(1)优缺点:

a.这种方法其实和上面的方法类似,只不过将类实例化的过程交
	给了静态代码块去实现,也就是在类装载的时候,就执行静态
	代码块中的代码,初始化类的实例。优缺点和上面一样

b.结论:这种单例模式可用,但是也会造成内存的浪费

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 饿汉式之静态代码块 {
    public static void main(String[] args) {
        Singleton01 singleton01 = Singleton01.getInstance();
        Singleton01 s = Singleton01.getInstance();
        System.out.println(s == singleton01);
        System.out.println(s.hashCode() == singleton01.hashCode());
    }
}

class Singleton01{
    // 1.构造器私有化,外部不能new
    private Singleton01(){

    }
    // 2.本类内部创建实例
    private static Singleton01 singLeTon;

    static {  // 在静态代码块中, 创建对象
        singLeTon = new Singleton01();
    }

    // 3.对外提供一个公共的静态方法 返回实例对象
    public static Singleton01 getInstance(){
        return singLeTon;

    }
}

3.1.3懒汉式(线程不安全)

(1)优缺点:

a.起到了lazy loading的效果,但是只能在单线程下使用

b.如果在多线程下,一个线程进入了if(singleton == null)判断语句,
	还来不及执行,另一个线程也判断通过,这是便会产生多个实例,
	所以多线程下不可以使用这种方法

c.结论:在实际开发中,不要使用这种方式

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 懒汉式之线程安全 {
    public static void main(String[] args) {
        Singleton03 singleton03 = Singleton03.getInstance();
        Singleton03 singleton04 = Singleton03.getInstance();
        System.out.println(singleton03 == singleton04);
        System.out.println(singleton03.hashCode());
        System.out.println(singleton04.hashCode());
    }
}

class Singleton03{

    private static Singleton03 singleton03;

    private Singleton03(){

    }

    // 提供一个静态的共有方法,加入同步处理的代码,解决线程安全问题 即懒汉式
    public static synchronized Singleton03 getInstance(){
        if (singleton03 == null){
            singleton03 = new Singleton03();
        }
        return singleton03;
    }

}

3.1.4 懒汉式(线程安全,同步方法)

(1)优缺点:

a.解决了线程安全问题

b.效率太低了,每个线程在想获得类的实例的时候,执行
	getInstance方法都要进行同步,而其实这个方法只执行
	一次就够了,后面想获得该实例直接return就行了,方法
	进行同步效率是太低了

c.结论:实际开中,不推荐使用

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 懒汉式之线程不安全 {
    public static void main(String[] args) {
        Singleton02 singleton02 = Singleton02.getInstance();
        Singleton02 singleton021 = Singleton02.getInstance();
        System.out.println(singleton02 == singleton021);
        System.out.println(singleton02.hashCode());
        System.out.println(singleton021.hashCode());
    }
}

class Singleton02{

    private static Singleton02 singleton02;

    private Singleton02(){

    }

    // 提供一个静态的共有方法,当使用到该方法时,才去创建instance 即懒汉式
    public static Singleton02 getInstance(){
        if (singleton02 == null){
            singleton02 = new Singleton02();
        }
        return singleton02;
    }

}

3.1.5 懒汉式(线程安全,同步代码块)

(1)优缺点:

a.跟第三个遇到的情景一样,假如一个线程进入了if(singleton == null)
	判断语句,还来不及执行,另一个线程也判断通过,这是便会产生
	多个实例,所以多线程下不可以使用这种方法

b.结论:在实际开发中,不要使用。

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 懒汉式之假_线程安全且同步 {
    public static void main(String[] args) {

    }
}

class Singleton04{

    private static Singleton04 singleton04;

    private Singleton04(){

    }

    // 提供一个静态的共有方法, 即懒汉式
    public static Singleton04 getInstance(){
        if (singleton04 == null){ // 但其实在这里就已经产生线程不安全了
            // 加入同步处理的代码,解决线程安全问题
            synchronized (Singleton04.class){
                singleton04 = new Singleton04();
            }
        }
        return singleton04;
    }

}

3.1.6 双重检查

(1)优缺点:

a.Double-check概念是多线程开发中常用到的,就是进行两
	次if(singleton == null)检查

b.避免反复进行方法同步

c.线程安全:延迟加载,效率较高

d.结论:实际开发中,推荐使用

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 双重检查 {
    public static void main(String[] args) {
        Singleton05 singleton05 = Singleton05.getInstance();
        Singleton05 singleton06 = Singleton05.getInstance();
        System.out.println(singleton05 == singleton06);
        System.out.println(singleton05.hashCode());
        System.out.println(singleton06.hashCode());

    }
}

class Singleton05{
    private static volatile Singleton05 singleton05;

    private Singleton05(){

    }

    // 提供一个静态的方法,加入双重检查代码 解决线程安全问题,同时解决懒加载问题
    public static synchronized Singleton05 getInstance(){
        if (singleton05 == null){
            synchronized (Singleton05.class){
                if (singleton05 == null){
                    singleton05 = new Singleton05();
                }
            }
        }
        return singleton05;
    }
}

3.1.7 静态内部类

(1)优缺点:

a.这种方法采用了类装载的机制保证初始化只有一个线程

b.静态内部类方式在Singleton06类被装载的时候并不会立即实例化,
	而是在需要实例化时,调用getInstance方法,才会去装载
	SingletonInstance类,从而完成Singleton06实例化

c.类的静态属性只会在第一次加载类的时候初始化,所以我们这里
	利用了JVM保证了线程安全,在类进行初始化的时候,别的线
	程是进不来的

d.优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高

e.结论:推荐使用

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 静态内部类 {
    public static void main(String[] args) {
        Singleton06 singleton06 = Singleton06.getInstance();
        Singleton06 singleton07 = Singleton06.getInstance();
        System.out.println(singleton06 == singleton07);
        System.out.println(singleton06.hashCode());
        System.out.println(singleton07.hashCode());
    }
}

class Singleton06{
    private Singleton06(){

    }

    // 静态内部类 提供一个静态属性 Singleton06
    private static class SingletonInstance{
        private static final Singleton06 SINGLETON_06 = new Singleton06();

    }

    // 提供一个静态的方法 直接返回SingletonInstance.SINGLETON_06
    public static  synchronized Singleton06 getInstance(){

        return SingletonInstance.SINGLETON_06;
    }
}

3.1.8 枚举

(1)优缺点:

a.借用jdk1.5中添加的枚举来实现单例模式,不仅能避免多线程同步
	问题,而且还能防止反序列化重新创建新的对象。

b.结论:推荐使用

(2)代码示例:

package com.pattern.设计模式.单例模式;

public class 枚举 {
    public static void main(String[] args) {
        Singleton07 singleton07 = Singleton07.INSTANCE;
        Singleton07 singleton08 = Singleton07.INSTANCE;
        System.out.println(singleton07 == singleton08);
        System.out.println(singleton07.hashCode());
        System.out.println(singleton08.hashCode());

        singleton07.shallow();

    }
}

enum Singleton07{
    INSTANCE;
    public void shallow(){
        System.out.println("OK!!!!!!");
    }

}

工厂模式

工厂模式 等等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值