文章目录

  • 面向对象设计的基本原则:
  • 单例模式 (常用)
    • 常见应用场景:
    • 常见的五种单例模式实现方式:
    • 五种单例模式的代码实现:
  • 工厂模式 (常用)
    • 工厂模式的分类:
    • 应用场景
    • 三种模式下的代码实现和UML图:
  • 建造者模式 (常用)
    • 代码实现和UML图
  • 原型模式
  • 创建型模式总结

面向对象设计的基本原则:

  • OCP (开闭原则, Open-Closed Principle) : 一个软件的实体应当对扩展开放,对修改关闭。即当要添加一个新功能时,不要修改已有的类,而是重新写一个类实现这个功能。
  • DIP (依赖倒转原则, Dependence Inversion Principle ) : 要针对接口编程,不要针对实现编程。
  • LoD (迪米特法则, Law of Demeter) : 只与你直接的朋友通信,而避免和陌生人通信。

单例模式 (常用)

作用:
  保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

常见应用场景:

  • Windows的Task Manager (任务管理器)就是很典型的单例模式
  • windows的Recycle Bin (回收站)也是典型的单例应用。在整个系统运行过程中,回收站-直维护着仅有的一个实例。
  • 项目中,读取配置文件的类, 一般也只有一个对象。 没有必要每次使用配置文件数据,每次new-个对象去读取。
  • 网站的计数器, 一般也是采用单例模式实现,否则难以同步。
  • 应用程序的日志应用, 一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态 ,因为只能有一个实例去操作,否则内容不好追加。
  • 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
  • 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。
  • Application也是单例的典型应用( Servlet编程中会涉及到)
  • 在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理
    在servlet编程中,每个Servlet也是单例
  • 在spring MVC框架/struts1框架中,控制器对象也是单例

单例模式的优点:

  • 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
  • 单例模式可以在系统设置全局的访问点 ,优化环共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理

常见的五种单例模式实现方式:

  • 主要:

    • 饿汉式(线程安全,调用效率高。但是,不能延时加载。)
    • 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。);在用的使用才加载。并发效率资源第。
  • 其他:
    • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用);这个模式将同步内容下方到if内部,提高了执行的效率不必每次获取对象时都进行同步,只有第一次才同步创建了以后就没必要了。
    • 静态内部类式(线程安全,调用效率高。但是,可以延时加载);也是一种懒加载的方式。兼备了并发高效调用和延迟加载的优势!
    • 枚举单例(线程安全,调用效率高,不能延时加载);实现简单,枚举本身就是单例模式。由JVM从根本上提供保障!避免通过反射和反序列化的漏洞!

如何选用
单例对象占用资源少,不需要延时加载:

  • 枚举式好于饿汉式

单例对象占用资源大,需要延时加载:

  • 静态内部类式好于懒汉式

五种单例模式的代码实现:

饿汉模式:

/** 饿汉式单例模式*/
public class SingletonDemo1 {//初始化类时,立即加载这个对象(没有延时加载的优势,因为不一定要使用,立即加载可能会浪费资源)//加载类时,因为创建对象是线程安全的,不需要添加关键字synchronized(加锁),所以饿汉式是天然线程安全的private static SingletonDemo1 instance = new SingletonDemo1();//将构造方法私有化private SingletonDemo1(){}//提供一个获得对象的方法,方法没有同步,调用效率高public static SingletonDemo1 getInstance(){return instance;}
}

懒汉式:

/* * 懒汉式单例模式*/
public class SingletonDemo2 {//类初始化时,不立即初始化对象(延时加载,在要使用的时候才进行加载)private static SingletonDemo2 instance;//将构造方法私有化private SingletonDemo2(){}//方法同步,调用效率高public static synchronized SingletonDemo2 getInstance(){if(instance==null){instance = new SingletonDemo2();}return instance;}
}

双重检测锁式:

/* * 双重检测锁式单例模式*/
public class SingletonDemo3 {private static SingletonDemo3 instance = null;//将构造方法私有化private SingletonDemo3(){}//这个模式将同步内容下方到if内部,提高了执行的效率不必每次获取对象时都进行同步,只有第一次才同步创建了以后就没必要了。public static  SingletonDemo3 getInstance(){if(instance==null){SingletonDemo3 sc;synchronized(SingletonDemo3.class){sc = instance;if(sc==null){synchronized(SingletonDemo3.class){if(sc==null){sc = new SingletonDemo3();}}instance = sc;}}}return instance;}
}

静态内部类式:

/* * 静态内部类式单例模式*/
public class SingletonDemo4 {/** 要点:-外部类没有static属性,则不会像饿汉式那样立即加载对象。-只有真正调用getInstance0,才会加载静态内部类。加载类时是线程安全的。 instance是static final类型,保证了内存中只有这样一个实例存在 ,而且只能被赋值一次,从而保证了线程安全性.-兼备了并发高效调用和延迟加载的优势!*/ private static class SingletonClassInstance{private static final SingletonDemo4 instance = new SingletonDemo4();}public static SingletonDemo4 getinstance(){return SingletonClassInstance.instance;}//将构造方法私有化private SingletonDemo4(){}}

枚举式:

/** 枚举式单例模式*/
public enum SingletonDemo5 {//这个枚举元素,本事就是单例; 缺点是不能延时加载INSTANCE;//添加自己需要的操作public void singletonOperarion(){}
}

  以上五种单例模式除了枚举式,其他的都有可能会被反射和反序列化破解;下面方式可以防止这种情况的发生。

import java.io.ObjectStreamException;/* * 懒汉式单例模式(防止通过反射和反序列化进行破解)*/
public class SingletonDemo6 {//类初始化时,不立即初始化对象(延时加载,在要使用的时候才进行加载)private static SingletonDemo6 instance;//将构造方法私有化private SingletonDemo6(){//防止通过反射使用私有的构造器if(instance!=null){throw new RuntimeException();}}//方法同步,调用效率高public static synchronized SingletonDemo6 getInstance(){if(instance==null){instance = new SingletonDemo6();}return instance;}//防止通过反序列化破坏单例模式,如果定义了readResolve()则直接返回此方法指定的对象。不需要单独再创建新对象private Object readResolve() throws ObjectStreamException{return instance;}
}

五种单例模式在多线程下的效率情况:


注:数据在不同的环境下可能会有点偏差。


工厂模式 (常用)

作用:
  实现了创建者和调用者的分离。

核心本质:

  • 实例化对象,用工厂方法代替new操作。
  • 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。

工厂模式的分类:

  • 简单工厂模式:

    • 用来生产同一等级结构中的任意产品。 (对于增加新的产品,需要修改已有代码)
    • 虽然某种程度不符合设计原则,但实际使用最多。
  • 方法模式:
    • 用来生产同一等级结构中的固定产品。( 支持增加任意产品);缺点:需要的类可能太多了。
    • 不修改已有类的前提下,通过增加新的工厂类实现扩展。
  • 抽象工厂模式:
    • 用来生产不同产品族的全部产品。( 对于增加新的产品,无能为力;支持增加产品族)
    • 不可以增加产品,可以增加产品族

应用场景

  • JDK中Calendar的getInstance方法
  • JDBC中Connection对象的获取
  • Hibernate中SessionFactory创建Session
  • spring中IOC容器创建管理bean对象
  • XML解析时的DocumentBuilderFactory创建解析器对象
  • 反射中Class对象的newInstance()

三种模式下的代码实现和UML图:

用于测试的类:

public interface Car {void run();
}
public class Audi implements Car{@Overridepublic void run() {System.out.println("奥迪在跑");}
}
public class Byd implements Car{@Overridepublic void run() {System.out.println("比亚迪在跑");}
}

简单工厂实现:

/** 简单工厂类*/
public class CarFactory1 {public static Car createAudi(){return new Audi();}public static Car createByd(){return new Byd();}
}

测试类:

/** 简单工厂情况下*/
public class Client02 {public static void main(String[] args) {Car c1 = CarFactory1.createAudi();Car c2 = CarFactory1.createByd();c1.run();c2.run();}
}

简单工厂下的UML图:

方法模式工厂:

工厂方法模式要点:

  • 为了避免简单工厂模式的缺点,不完全满足OCP。
  • 工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。
  • 每一种产品都有一个工厂类对应,当需要添加产品时,只需要添加新的类即可,不需要修改原来的代码。

代码实现:

接口:

public interface CarFactory {Car createCar();
}

奥迪工厂:

public class AudiFactory implements CarFactory{@Overridepublic Car createCar() {return new Audi();}
}

比亚迪工厂:

public class BydFactory implements CarFactory{@Overridepublic Car createCar() {return new Byd();}
}

测试类:

/** 使用方法工厂模式*/
public class Client03 {public static void main(String[] args) {Car c1 = new AudiFactory().createCar();Car c2 = new BydFactory().createCar();c1.run();c2.run();}
}

方法工厂的UML图:

抽象工厂模式:

作用:

  • 用来生产不同产品族的全部产品。( 对于增加新的产品,无能为力;支持增加产品族)
  • 抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

代码实现:

引擎产品:

package abstractFactory;
/**引擎接口 */
public interface Engine {void run();void start();
}//高端引擎
class LuxuryEngine implements Engine{@Overridepublic void run() {System.out.println("转的快!");}@Overridepublic void start() {System.out.println("启动快!可以自动暂停");}
}//低端引擎
class LowEngine implements Engine{@Overridepublic void run() {System.out.println("转的慢!");}@Overridepublic void start() {System.out.println("启动慢!");}
}

座椅产品:

package abstractFactory;
/** 座椅*/
public interface Seat {void massage();
}//高端座椅
class LuxurySeat implements Seat{@Overridepublic void massage() {System.out.println("可以自动按摩");}
}//低端座椅
class LowSeat implements Seat{@Overridepublic void massage() {System.out.println("不能自动按摩");}
}

轮胎产品:

package abstractFactory;//轮胎接口
public interface Tyre {void revolve();
}//高端轮胎
class LuxuryTyre implements Tyre{@Overridepublic void revolve() {System.out.println("旋转不磨损");}
}//低端轮胎
class LowTyre implements Tyre{@Overridepublic void revolve() {System.out.println("旋转磨损");}
}

工厂接口:

package abstractFactory;public interface CarFactory {Engine CreateEngine();Seat CreateSeat();Tyre CreateTre();
}

高端产品族工厂:

package abstractFactory;
/** 高端产品族工厂*/
public class LuxuryCarFactory implements CarFactory{@Overridepublic Engine CreateEngine() {return new LuxuryEngine();}@Overridepublic Seat CreateSeat() {return new  LuxurySeat();}@Overridepublic Tyre CreateTre() {return new LuxuryTyre();}}

低端产品族工厂:

package abstractFactory;
/** 低端产品族工厂*/
public class LowCarFactory implements CarFactory{@Overridepublic Engine CreateEngine() {return new LowEngine();}@Overridepublic Seat CreateSeat() {return new  LowSeat();}@Overridepublic Tyre CreateTre() {return new LowTyre();}}

测试类:

package abstractFactory;public class Client {public static void main(String[] args) {CarFactory factory = new LuxuryCarFactory();Engine e = factory.CreateEngine();e.run();e.start();}
}

建造者模式 (常用)

应用场景:

  • 我们要建造一个复杂的产品。比如:神州飞船,Iphone。这个复杂的产品的创建。有这样个问题需要处理:装配这些子组件是不是有个步骤问题?
  • 实际开发中,我们所需要的对象构建时,也非常复杂,有很多步骤需要处理时。

建造模式的本质:

  • 分离了对象子组件的单独构造(由Builder来负责)和装配(由Director负责)。从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况下使用。
  • 由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。

开发中应用场景:

  • StringBuilder类的append方法
  • SQL中的PreparedStatement
  • JDOM中, DomBuilder、SAXBuilder

代码实现和UML图

飞船和零件类:

package 建造者模式;
/** 宇宙飞船*/
public class AirShip {private OrbitalModule orbitalModule;   //轨道舱private Engine engine;        //发动机private EscapeTower escapeTower;  //逃逸塔public void launch(){System.out.println("发射!");}public OrbitalModule getOrbitalModule() {return orbitalModule;}public void setOrbitalModule(OrbitalModule orbitalModule) {this.orbitalModule = orbitalModule;}public Engine getEngine() {return engine;}public void setEngine(Engine engine) {this.engine = engine;}public EscapeTower getEscapeTower() {return escapeTower;}public void setEscapeTower(EscapeTower escapeTower) {this.escapeTower = escapeTower;}}class OrbitalModule {private String name;public OrbitalModule(String name) {super();this.name = name;}
}class Engine {private String name;public Engine(String naem) {super();this.name= naem;}public String getName() {return name;}
}class EscapeTower {private String name;public EscapeTower(String name) {super();this.name = name;}
}

建造者接口:

/** 建造者接口*/
public interface AirShipBuilder {Engine builderEngine();OrbitalModule builderOrbitaModule();EscapeTower builderEscapeTower();
}

组装者接口:

public interface AirShipDirector {//组装飞船对象AirShip directAirShip();
}

构建者类:

package 建造者模式;
/** 构建者类*/
public class SxtAirShipBuilder implements AirShipBuilder{@Overridepublic Engine builderEngine() {System.out.println("构建发动机");return new Engine("发动机");}@Override  public OrbitalModule builderOrbitaModule() {System.out.println("构建逃逸塔");return new OrbitalModule("逃逸塔");}@Overridepublic EscapeTower builderEscapeTower() {System.out.println("构建轨道舱");return new EscapeTower("轨道舱");}
}

组装者类:

package 建造者模式;/** 组装者类,用于将零件组装成对象*/
public class SxtAirshipDirector implements AirShipDirector{private AirShipBuilder builder;public SxtAirshipDirector(AirShipBuilder builder){this.builder = builder; }@Override  //将组件组装成飞船public AirShip directAirShip() {Engine e = builder.builderEngine();OrbitalModule o = builder.builderOrbitaModule();EscapeTower et = builder.builderEscapeTower();//装配成飞船对象AirShip ship = new AirShip();ship.setEngine(e);ship.setEscapeTower(et);ship.setOrbitalModule(o);return ship;}
}

测试类:

public class Client {public static void main(String[] args) {AirShipDirector director = new SxtAirshipDirector(new SxtAirShipBuilder());AirShip ship = director.directAirShip();System.out.println(ship.getEngine().getName());ship.launch();}
}

UML图:


原型模式

原型模式介绍:

  • 通过new产生一 个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  • 就是java中的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点
  • 优势有:效率高(直接克隆,避免了重新执行构造过程步骤)。
  • 克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性值完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后,再修改克隆对象的值。

原型模式实现:

  • Cloneable接口和clone方法
  • Prototype(原型)模式中实现起来最困难的地方就是内存复制操作 ,所幸在Java中提供了clone()方法替我们做了绝大部分事情。

开发中的应用场景

  • 原型模式很少单独出现,-般是和工厂方法模式一起出现,通过clone的方法创建一个对象 ,然后由工厂方法提供给调用者。
  • spring中bean的创建实际就是两种:单例模式和原型模式。( 当然,原型模式需要和工厂模式搭配起来)

代码实现:

package 原型模式;import java.sql.Date;public class Sheep implements Cloneable{private String sname;private Date birthday;//重写克隆方法protected Object clone() throws CloneNotSupportedException{Object obj = super.clone();  //直接调用Object对象的clone()方法//添加如下代码实现深克隆(deep Clone);如果没有进行深坑,克隆出来的属性会指向同一个对象Sheep s = (Sheep) obj;s.birthday = (Date) this.birthday.clone();  //把属性也进行克隆return obj;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public Sheep() {}public Sheep(String sname, Date birthday) {super();this.sname = sname;this.birthday = birthday;}
}

测试类:

package 原型模式;import java.sql.Date;
/*** * 测试原型模式(深克隆)**/
public class Client {public static void main(String[] args) throws Exception {Date d = new Date(123456567L);Sheep s1 = new Sheep("shao利", d);System.out.println(s1);System.out.println(s1.getSname());System.out.println(s1.getBirthday());Sheep s2 = (Sheep)s1.clone();d.setTime(666666666666L);s2.setSname("多利");System.out.println(s2);System.out.println(s2.getSname());System.out.println(s2.getBirthday());}
}

创建型模式总结

创建型模式:都是用来帮助我们创建对象的!
单例模式:

  • 保证一个类只有一个实例,并且提供一 个访问该实例的全局访问点。

工厂模式:

  • 简单工厂模式:
       用来生产同一等级结构中的任意产品。( 对于增加新的产品,需要修改已有代码)
  • 工厂方法模式:
       用来生产同一等级结构中的固定产品。( 支持增加任意产品)
  • 抽象工厂模式:
       一用来生产不同产品族的全部产品。( 对于增加新的产品,无能为力;支持增加产品族)

建造者模式:

  • 分离了对象子组件的单独构造(由Builder来负责)和装配(由Director负责)。从而可以构造出复杂的对象。
  • 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式

原型模式:

  • 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式

创建型模式大全(Java讲解)相关推荐

  1. 从零开始学习Java设计模式 | 创建型模式篇:原型模式

    在本讲,我们来学习一下创建型模式里面的第四个设计模式,即原型模式. 概述 原型模式就是指用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象. 这段话读起来有点绕,是不是? ...

  2. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

  3. Java设计模式之五大创建型模式(附实例和详解)

    一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...

  4. Java学习--设计模式之创建型模式

    一.简介 创建型模式:这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象.这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活.创建型模式包括:工 ...

  5. 初探Java设计模式1:创建型模式(工厂,单例等)

    Java 设计模式 一直想写一篇介绍设计模式的文章,让读者可以很快看完,而且一看就懂,看懂就会用,同时不会将各个模式搞混.自认为本文还是写得不错的,花了不少心思来写这文章和做图,力求让读者真的能看着简 ...

  6. java创建型_Java创建型模式

    Java创建型模式 在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象.基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度.创建型模式通过以某种方式控制 ...

  7. Java创建型模式的讨论

    2019独角兽企业重金招聘Python工程师标准>>> 创建型模式抽象了实例化过程.它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类, ...

  8. JAVA设计模式 - 创建型模式总结

    JAVA设计模式 - 单例模式 JAVA设计模式 - 工厂方法模式 JAVA设计模式 - 抽象工厂模式 JAVA设计模式 - 原型模式 JAVA设计模式 - 建造者模式 1 . 创建型模式的定义 顾名 ...

  9. Java设计模式学习总结(4)——创建型模式之单例模式

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创建自己的对 ...

  10. Java设计模式学习总结(2)——创建型模式之工厂模式

    工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式.在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑 ...

最新文章

  1. 限制input输入小数只能到3位或者只能输入正整数(兼容ios)
  2. MySQL优化经验-值得细细品读
  3. centos7.3挂在移动硬盘(亲测)
  4. 世界杯十六强合影壁纸
  5. mysql删除有关联的数据库表_【数据库】mysql如何删除关联表
  6. UCSC数据库数据调用cruzdb
  7. iphone开发JSON库之BSJSONAdditions
  8. 阿里巴巴开发公约节选(日常编程较常用的一些)
  9. Microsoft Visual Studio Web 创作组件安装失败的解决方法
  10. Mac版IntelliJ IDEA上手的一些必要设置
  11. WPF—TreeView无限极绑定集合形成树结构
  12. BZOJ3997 TJOI2015组合数学(动态规划)
  13. java 性能优化:35 个小细节,让你提升 java 代码的运行效率
  14. 神来之笔-线程变量实践
  15. VMware下安装Raspbian树莓派系统
  16. 软件自动化测试框架STAF
  17. 数据分析之信用风险评分卡建立
  18. [转...转] 国内软件破解下载网站列表!
  19. qt保存文件的默认路径_Qt Quick QSettings 配置信息保存位置
  20. 【路漫漫其修远兮,吾将上下而求索】

热门文章

  1. java contains忽略大小写_关于java:字符串包含-忽略大小写
  2. excel删除无尽空白行_批量删除空白行其实很简单,这3中方法都能快速搞定,简单易学...
  3. SPECTRUM发布6种新型AWG任意波形发生器
  4. 每股收益具体怎么来的
  5. 传统蓝牙HCI Command(蓝牙HCI命令)详细介绍
  6. ecshop手机支付宝支付篡改金额BUG
  7. 51单片机指令系统详解
  8. CentOS 6.5 CentOS 7 rpm安装ftp服务端与ftp客户端
  9. 继屠呦呦后,下一个得诺奖的中国人可能是他?
  10. 3❤️Jenkins从零到壹❤️ :常用功能大全(JAVA 小虚竹)