降低系统的耦合度,使用者不需要关注对象创建的细节

一.单例模式

涉及到一个单一的类,这个类只能创建一个对象,这个类提供了一个可以唯一获得对象的方法,不需要外界实例化对象

1.饿汉式

类加载的时候对象就会被创建

  1. //饿汉式
  2. public class Singleton {
  3. //创建对象
  4. private static Singleton singleton=new Singleton();
  5. //私有化构造器
  6. private Singleton(){
  7. }
  8. //提供给外界获得对象的类
  9. public static Singleton getSingleton(){
  10. return singleton;
  11. }
  12. }

2.懒汉式

在第一次调用时创建对象

  1. //懒汉式
  2. public class Singleton {
  3. //声明对象
  4. private static Singleton singleton=null;
  5. //私有化构造器
  6. private Singleton(){
  7. }
  8. //提供给外界获得对象的类
  9. public static Singleton getSingleton(){
  10. if(singleton==null){
  11. //如果等于null 创建对象
  12. singleton=new Singleton();
  13. }
  14. return singleton;
  15. }
  16. }

线程安全版(双重检查)

  1. //懒汉式(线程安全的)
  2. public class Singleton {
  3. //声明对象
  4. private static volatile Singleton singleton=null;
  5. //私有化构造器
  6. private Singleton(){
  7. }
  8. //提供给外界获得对象的类
  9. public static Singleton getSingleton(){
  10. if(singleton==null){
  11. synchronized (Singleton.class){
  12. if(singleton==null){
  13. //如果等于null 创建对象
  14. singleton=new Singleton();
  15. }
  16. }
  17. }
  18. return singleton;
  19. }
  20. }

静态内部类版(线程安全)

  1. //懒汉式(线程安全的)
  2. public class Singleton {
  3. //私有化构造器
  4. private Singleton(){
  5. }
  6. public static class inner{
  7. private static final Singleton singleton= new Singleton();
  8. }
  9. public Singleton getSingleton(){
  10. return inner.singleton;
  11. }
  12. }

二.工厂模式

在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦。

1.简单工厂模式

简单工厂包含如下角色:
抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
具体产品 :实现或者继承抽象产品的子类
具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。
image.png

  1. public class SimpleCoffeeFactory {
  2. public Coffee createCoffee(String type) {
  3. Coffee coffee = null;
  4. if("americano".equals(type)) {
  5. coffee = new AmericanoCoffee();
  6. } else if("latte".equals(type)) {
  7. coffee = new LatteCoffee();
  8. }
  9. return coffee;
  10. }
  11. }

优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避 免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户 代码修改的可能性,更加容易扩展。
缺点:
增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。

2.静态工厂模式

  1. public class SimpleCoffeeFactory {
  2. public static Coffee createCoffee(String type) {
  3. Coffee coffee = null;
  4. if("americano".equals(type)) {
  5. coffee = new AmericanoCoffee();
  6. } else if("latte".equals(type)) {
  7. coffee = new LatteCoffee();
  8. }
  9. return coffee;
  10. }
  11. }

3.工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。
结构
工厂方法模式的主要角色:
抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂
方法来创建产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同
具体工厂之间一一对应。
image.png

  1. //咖啡工厂类
  2. public interface CoffeeFactory {
  3. public Coffee createCoffee(String name);
  4. }
  5. //美式咖啡工厂类,专门生产美式咖啡
  6. public class AmericanCoffeeFactory implements CoffeeFactory{
  7. @Override//生成美式咖啡
  8. public Coffee createCoffee(String name) {
  9. return new AmericanCoffee();
  10. }
  11. }
  12. //咖啡店类
  13. public class CoffeeStore {
  14. private CoffeeFactory factory;
  15. public void setFactory(CoffeeFactory factory){
  16. this.factory=factory;
  17. }
  18. public Coffee createCoffee(){
  19. Coffee meishi = factory.createCoffee("meishi");
  20. return meishi;
  21. }
  22. }

4.抽象工厂模式

现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点,如提拉米苏、抹茶慕斯等,要是按照工厂方法 模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类 爆炸情况。其中拿铁咖啡、美式咖啡是一个产品等级,都是咖啡;提拉米苏、抹茶慕斯也是一个产品等 级;拿铁咖啡和提拉米苏是同一产品族(也就是都属于意大利风味),美式咖啡和抹茶慕斯是同一产品族(也就是都属于美式风味)。所以这个案例可以使用抽象工厂模式实现
image.png
抽象工厂

  1. public interface DessertFactory {
  2. Coffee createCoffee();
  3. Dessert createDessert();
  4. }

具体工厂

  1. //美式甜点工厂
  2. public class AmericanDessertFactory implements DessertFactory {
  3. public Coffee createCoffee() {
  4. return new AmericanCoffee();
  5. }
  6. public Dessert createDessert() {
  7. return new MatchaMousse();
  8. }
  9. }
  10. //意大利风味甜点工厂
  11. public class ItalyDessertFactory implements DessertFactory {
  12. public Coffee createCoffee() {
  13. return new LatteCoffee();
  14. }
  15. public Dessert createDessert() {
  16. return new Tiramisu();
  17. }
  18. }

三.原型模式

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
结构
原型模式包含如下角色:
抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象
image.png

1.浅克隆

创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。

  1. //浅克隆
  2. public class Realizetype implements Cloneable{
  3. @Override
  4. protected Realizetype clone() throws CloneNotSupportedException {
  5. return (Realizetype) super.clone();
  6. }
  7. }

2.深克隆

创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
为每一个对象属性都进行一次克隆

  1. public class sheep implements Cloneable, Serializable {
  2. private int age;
  3. private String name;
  4. public sheep friend=null;
  5. public sheep() {
  6. }
  7. public sheep(int age, String name) {
  8. this.age = age;
  9. this.name = name;
  10. }
  11. public int getAge() {
  12. return age;
  13. }
  14. public void setAge(int age) {
  15. this.age = age;
  16. }
  17. public String getName() {
  18. return name;
  19. }
  20. public void setName(String name) {
  21. this.name = name;
  22. }
  23. //深拷贝
  24. protected sheep clone2(){
  25. sheep sheep=null;
  26. try {
  27. sheep=(sheep)super.clone();
  28. if(sheep.friend!=null){
  29. sheep.friend=sheep.friend.clone2();
  30. }
  31. } catch (CloneNotSupportedException e) {
  32. e.printStackTrace();
  33. }
  34. return sheep;
  35. }
  36. }

四.建造者模式

将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况。
由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。
建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。
结构
抽象建造者类(Builder):这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的部件对象的创建。
具体建造者类(ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。
产品类(Product):要创建的复杂对象。
指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
image.png

  1. public class Bike {
  2. private String frame;//车架
  3. private String seat;//车座
  4. public Bike() {
  5. }
  6. public Bike(String frame, String seat) {
  7. this.frame = frame;
  8. this.seat = seat;
  9. }
  10. public String getFrame() {
  11. return frame;
  12. }
  13. public void setFrame(String frame) {
  14. this.frame = frame;
  15. }
  16. public String getSeat() {
  17. return seat;
  18. }
  19. public void setSeat(String seat) {
  20. this.seat = seat;
  21. }
  22. }

建造者

  1. public abstract class Builder {
  2. public Bike bike=new Bike();//只是声明了一个自行车,具体部件没有组装
  3. public abstract void buildFrame();
  4. public abstract void buildSeat();
  5. public abstract Bike createBike();
  6. }
  7. public class OFOBuilder extends Builder{
  8. @Override
  9. public void buildFrame() {
  10. bike.setFrame("ofoFrame");
  11. }
  12. @Override
  13. public void buildSeat() {
  14. bike.setSeat("ofoSeat");
  15. }
  16. @Override
  17. public Bike createBike() {
  18. return this.bike;
  19. }
  20. }

指挥者

  1. public class Director {
  2. Builder builder;
  3. public Director(Builder builder) {
  4. this.builder = builder;
  5. }
  6. //组装
  7. public Bike construct(){
  8. builder.buildFrame();
  9. builder.buildSeat();
  10. return builder.createBike();
  11. }
  12. }

建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在指挥者类中对整体而言可以取得比较好的稳定性。