设计模式之创建型模式

2023-05-16

文章目录

    • 创建型模式(Creational Pattern)
      • 1.1单例模式(Singleton Pattern)
      • 1.2工厂模式(Factory Pattern)
      • 1.3抽象工厂模式(Abstract Factory Pattern)
      • 1.4建造者模式(Builder Pattern)
      • 1.5原型模式(Prototype Pattern)

创建型模式主要包括单例模式,工厂模式,抽象工厂模式,建造者模式以及原型模式

创建型模式(Creational Pattern)

该类型的设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,不是使用 new 运算符直接实例化对象,将软件模块中对象的创建和对象的使用分离。外界对于这些对象只需要知道它们的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。

1.1单例模式(Singleton Pattern)

单例模式中某个类在系统中只有一个实例,且只能由该类自己负责创建自己的唯一实例,并向外提供访问接口。该类被称为单例类。单例类要保证构造函数是私有的,并提供一个自身的静态私有成员变量以及一个共有的静态工厂方法向外提供唯一实例。

单例模式实现方式

1)懒汉式,线程不安全

//不支持多线程,严格意义上不算单例模式
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static Singleton getInstance() {
    if(instance == null) {
      instance = new Singleton();
    }
    return instance;
  }
}

2)懒汉式,线程安全

//效率低,第一次调用时才初始化,避免内存浪费
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static synchronized Singleton getInstance() {
    if(instance == null) {
      instance = new Singleton();
    }
    return instance;
  }
}

3)饿汉式

//类加载时就初始化,浪费内存,易产生垃圾对象
public class Singleton {
  private static Singleton instance = new Singleton();
  private Singleton(){}
  public static Singleton getInstance() {
    return instance;
  }
}

4)双重校验锁

//安全且在多线程情况下能保持高性能
public class Singleton {
  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;
  }
}

5)静态内部类

//利用classloader机制保证初始化instance时只有一个线程。方式3中singleton类被加载后instance就会被实例化。而该方式只有在显式调用getInstance方法后显式装载静态内部类,实例化instance。
public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  
}

单例模式优缺点

优点:系统中只有一个对象,节约系统资源,减少内存开销

缺点:不能扩展,单例类职责过重,一定程度上违背单一职责原则,单例类将创建和使用功能融在一起

单例模式适用场景

系统中只需要一个实例对象,比如要生产唯一序列号,设备管理器等

1.2工厂模式(Factory Pattern)

工厂模式也叫多态工厂模式。在工厂模式中,父类负责定义创建对象的接口,子类负责实现具体的实例。比如先定义一个抽象的汽车工厂类,然后定义具体的轿车,跑车工厂类来实现抽象汽车工厂类中定义的方法,将创建过程延迟到子类中进行。这样,如果出现新的车型如卡车时,只需要引入新的卡车工厂类即可,符合开闭原则。

工厂模式实现

public class FactoryPatternDemo {
  public static void main(String[] arg) {
    VehicleFactory factory = new VehicleFactory();
    
    //轿车
    Vehicle car = factory.getVehicle("car");
    car.run();
    //卡车
    Vehicle truck = factory.getVehicle("truck");
    truck.run();
  }
}


public class VehicleFactory {
  public Vehicle getVehicle(String type) {
    if(type == null) return null;
    else if(type.equals("car")) {
      return new Car();
    } else if(type.equals("truck")) {
      return new Truck();
    }
    return null;
  }
}


public interface Vehicle {
  public void run();
}
public class Car implements Vehicle {
  public void run() {
    System.out.print("Car is runing");
  }
}
public class Truck implements Vehicle {
  public void run() {
    System.out.print("Truck is runing");
  }
}

工厂模式的优缺点

优:扩展性高,只关注调用接口不关注具体实现细节,增加新功能无需修改源代码;

缺:每一个产品都需要一个具体的实现类,系统中类的个数成倍增加

工厂模式的适用场景

在任何需要复杂对象的场景中都可以使用工厂模式。比如,日志记录器,可以记录在本地磁盘,或远程服务器等;服务器连接框架,不同的协议实现不同的连接类。

1.3抽象工厂模式(Abstract Factory Pattern)

工厂模式是在具体实现上做了抽象得到工厂类,抽象工厂模式是在工厂类之上做了进一步抽象(工厂模式是先定义工厂,由工厂生产对象;抽象工厂模式是先定义抽象工厂,由抽象工厂生成具体工厂,再由具体工厂生成对象)。即抽象工厂模式是工厂的工厂。抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。相较于工厂模式,抽象工厂可以提供多个产品对象而非单一对象。

产品等级结构:即产品的继承结构。一个抽象类是电视,子类是具体品牌,则父类与子类构成了产品等级结构。
产品族:指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
产品族难扩展,产品等级易扩展。
工厂模式针对的是一个产品等级结构(一个工厂一种产品),而抽象工厂模式则需要面对多个产品等级结构(一个工厂多种产品)。当系统需要工厂生产的产品不是单一产品而是属于不同类型的产品时,需要使用抽象工厂。

抽象工厂模式的实现

public class AbstractFactoryPatternDemo {
  public static void main(String[] arg) {
    //创建一个手机工厂和一个电脑工厂
    AbstractFactory phoneFactory = FactoryProducer.getFactory("phone");
    AbstractFactory computerFactory = FactoryProducer.getFactory("computer");
    
    //生产一个智能机,一个老年机
    Phone smartPhone = phoneFactory.getPhone("smart");
    Phone keyBdPhone = phoneFactory.getPhone("senior");
    smartPhone.call();
    keyBdPhone.call();
    
    //生产一个商务本,一个游戏本
    Computer commercialPC = compuerFactory.getPC("commercial");
    Computer gamePC = compuerFactory.getPC("game");
    commercialPC.sendMail();
    gamePC.sendMail();
  }
}


public class FactoryProducer {
  public static AbstractFactory getFactory(String type) {
    if(type.equals("phone")) {
      return new PhoneFactory();
    } else if(type.equals("computer")) {
      return new ComputerFactory();
    }
    return null;
  }
}


public abstract class AbstractFactory {
  //抽象类与接口的区别
  //语法上,大致无异。接口里的变量是用public static final修饰的
  //应用上,抽象类是类,是对事物的抽象,接口一般是公共的属性和方法
  public abstract Phone getPhone(String type);
  public abstract Computer getPC(String type);
}


//手机工厂
public class PhoneFactory extends AbstractFactory {
  public Computer getPC(String type) {
    return null;
  }
  public Phone getPhone(String type) {
    if(type.equals("smart")) {
      return new SmartPhone();
    } else if(type.equals("senior")) {
      return new SeniorPhone();
    }
    return null;
  }
}
public interface Phone {
  public void call();
}
public class SmartPhone implements Phone {
  public void call() {
    System.out.print("smart phone");
  }
}
public class SeniorPhone implements Phone {
  public void call() {
    System.out.print("senior phone");
  }
}


//电脑工厂
public class ComputerFactory extends AbstractFactory {
  public Computer getPC(String type) {
    if(type.equals("commercial")) {
      return new CommercialPC();
    } else if(type.equals("game")) {
      return new GamePC();
    }
    return null;
  }
  public Phone getPhone(String type) {
    return null;
  }
}
public interface Computer {
  public void snedMail();
}
public class CommercialPC implements Computer {
  public void sendMail() {
    System.out.print("commercial");
  }
}
public class GamePC implements Computer {
  public void sendMail() {
    System.out.print("game");
  }
}

抽象工厂模式的优缺点

当一个产品族中的多个对象被设计成一起工作时,能保证客户端始终只使用同一个产品族中的对象。利于需要根据当前环境来决定其行为的软件系统
增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”
不利于增加新类型的工厂即纵向易扩展,横向难改变
抽象工厂模式的使用场景

系统中有多个产品族,每次只使用其中的一个。

1.4建造者模式(Builder Pattern)

建造者模式使用多个简单的对象一步一步构建成一个复杂的对象,通过将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。用户不需要了解复杂对象的具体细节,只需提供复杂对象的类型和内容信息就可构建复杂对象。每一个建造者是相对独立的,可以很方便替换或增添新的建造者,符合开闭原则。

建造者模式包含四个角色:抽象建造者为创建一个产品对象的各个部件指定抽象接口;具体建造者实现了抽象建造者接口;产品角色是被构建的复杂对象;指挥者负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在指挥者construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。指挥者类的作用主要有两个:一方面它隔离了客户与生产过程;另一方面它负责控制产品的生成过程,指挥者针对抽象建造者编程。

如果系统中只有一个建造者的话,可以省略抽象建造者;若抽象建造者被省略可进一步省略指挥者。
在这里插入图片描述

建造者模式的实现

对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。

public class BuilderPatternDemo {
  public static void main(String[] arg) {
    ProductOneBuilder builderOne = new ProductOneBuilder();
    Director director = new Director(ProductOneBuilder);
    Product p = director.construct();
    
    ProductTwoBuilder builderTwo = new ProductTwoBuilder();
    director.setDirector(builderTwo);
    Product pp = director.construct();
  }
}


public class Product {
  public String name;
  public String type;
}


public abstract class Builder {
  private Product product = new Product();
  public abstract void buildPartA();
  public abstract void buildPartB();
  public Product getResult() {
    return product;
  }
}


public class ProductOneBuilder extends Builder {
  public void buildPartA() {
    System.out.print("partA of Product one");
  }
  public void buildPartB() {
    System.out.print("partB of Product one");
  }
} 
public class ProductTwoBuilder extends Builder {
  public void buildPartA() {
    System.out.print("partA of Product two");
  }
  public void buildPartB() {
    System.out.print("partB of Product two");
  }
} 


public class Director {
  Builder builder = null;
  public Director(Builde builder) {
    this.builder = builder;
  }
  public void setDirector(Builder builder) {
    this.builder = builder;
  }
  //具体的构造过程
  public Product construct() {
    builder.buildPartA();
    builder.buildPartB();
    return build.getResult();
  }
}

建造者模式的优缺

优:客户无需了解产品内部细节,将产品自身与产品创建过程解耦,相同的创建过程可以创建不同的产品对象

缺:建造者模式创建的产品内部组件相似,有共同点,内部属性相互依赖需要指定生成顺序,若内部之间差异大则不宜用。

建造者模式的适用场景

对象内部结构复杂或内部属性有依赖需指定生成顺序。

1.5原型模式(Prototype Pattern)

当直接创建对象的代价较高时,可以采用原型模式创建重复对象。原型模式通过实现一个原型接口利用已有的原型对象来创建当前对象的克隆。原型模式是通过拷贝一个现有对象生成新对象。java中浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

原型模式的实现

public class Sheep implements Cloneable {
  private String name;
  public Sheep(String name) {
    this.name = name;
  }
  public String getName() {
    return this.name;
  }
  public void setName(String name) {
    this.name = name;
  }
  
  public Object clone() {
    Object clone = null;
    try {
      clone = super.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    return clone;
  }
}


public class PrototypeDemo {
  public static void main(String[] arg) {
    Sheep dolly = new Sheep("Dolly");
    Sheep cloneSheep = (Sheep)dolly.clone();
  }
}
//深拷贝
public class Sheep implements Serializable,Cloneable {
  private String name;
  private Sheep father;
  public Sheep(String name) {
    this.name = name;
    this.faher = null;
  }
  public Sheep(String name, Sheep father) {
    this.name = name;
    this.father = father;
  }
  public String getName() {
    return this.name;
  }
  public void setName(String name) {
    this.name = name;
  }
  
  //方式一
  public Object clone() {
    Object clone = null;
    try {
      clone = super.clone();
      Sheep vice = (Sheep) clone;
      vice.father = (Sheep) father.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    return clone;
  }
  
  //方式二
  public Object deepClone() {
    Object clone = null;
    ByteArrayOutputStream bos = null;
    ByteArrayInputStream bis = null;
    ObjectOutputStream oos = null;
    ObjectInputStream ois = null;
    
    try {
      bos = new ByteArrayOutputStream();
      oos = new ObjectOutputStream(bos);
      oos.writeObject(this);
      
      bis = new ByteArrayInputStream(bos.toByArray());
      ois = new ObjectInputStream(bis);
      clone = ois.readObject();
    } catch (Exception e) {
      e.printStackTree();
    } finally {
      try {
        bos.close();
        oos.close();
        bis.close();
        ois.close();
      } catch (Exception e) {
         e.printStackTree();
      }
    }
    return clone;
  }
}


public class PrototypeDemo {
  public static void main(String[] arg) {
    Sheep dolly = new Sheep("Dolly", new Sheep("Mr.wang"));
    Sheep cloneSheep1 = (Sheep)dolly.clone();
    Sheep cloneSheep2 = (Sheep)dolly.deepClone();
  }
}

原型模式的优缺

优:性能提高,避开构造函数约束,

缺:克隆时需要考虑原对象所有功能,尤其当原对象引用了不支持序列化的间接对象或者包含循环结构时

原型模式的适用场景

创建对象时需要的资源多;或者一个对象多个修改者

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式之创建型模式 的相关文章

随机推荐

  • c#切割字符串几种方法

    1 xff0c 按单一字符切割 string s 61 34 abcdeabcdeabcde 34 string sArray 61 s Split 34 c 34 oreach string i in sArray Console Wri
  • 动态链接库与静态链接库的区别

    静态链接库与动态链接库都是共享代码的方式 xff0c 如果采用静态链接库 xff0c 则无论你愿不愿意 xff0c lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了 但是若使用 DLL xff0c 该 DLL 不必被包含在最终
  • ssm——小学期实训总结

    实训总结 经过这两个星期短暂的学习 xff0c 我学习了ssm的框架搭建与web前端设计基础 在第一个星期 xff0c 老师着重为我们讲了框架的原理 搭建与运用 xff1b 而在第二个星期 xff0c 重点则转移到了小组对项目的开发与研究上
  • 节点中心性

    文章目录 度中心性 Degree Centrality 特征向量中心性 Eigenvector Centrality Katz中心性 Katz Centrality Katz index PageRank中心性PageRank算法 接近中心
  • 机器学习面试知识点总结

    文章目录 计算学习理论过拟合与欠拟合过拟合欠拟合 偏差与方差最大似然估计与贝叶斯估计极大似然估计贝叶斯决策论贝叶斯估计 特征工程与特征选择特征工程逐层归一化特征选择 模型融合融合策略 评估方法与评价指标评估方法评价指标 优化算法正则化深度模
  • Multi-view graph convolutional networks with attention mechanism

    摘要 传统的图卷积网络关注于如何高效的探索不同阶跳数 hops 的邻居节点的信息 但是目前的基于GCN的图网络模型都是构建在固定邻接矩阵上的即实际图的一个拓扑视角 当数据包含噪声或者图不完备时 xff0c 这种方式会限制模型的表达能力 由于
  • An Empirical Study of Graph Contrastive Learning

    摘要 图对比学习在图表示学习领域树立了新的范式 xff0c 不需要人工标注信息 但对GCL的分析却寥寥无几 本文通过分析一般化的GCL范式的各个部分包括增强函数 xff0c 对比模式 xff0c 对比目标和负采样技术 xff0c 然后分析各
  • Data Augmentation

    自监督深度学习模型的精确性严重依赖于训练时数据的多样性和数据量 模型要想在更复杂任务上有较好的效果一般会有大量的隐藏单元 一般在训练过程中训练隐藏单元越多需要的数据越多 xff0c 即任务复杂度与参数量与需要的数据量成正比 由于训练复杂任务
  • Semi-Supervised and Self-Supervised Classification with Multi-View Graph Neural Networks

    摘要 图神经网络在图结构数据中取得了很好的效果但是大多数的模型使用的还是叫浅层的结构 xff0c 当模型层数加深时很容易过平滑 本文基于多视图来聚合更多的信息 我们首先设计两个互补的视图来描述全局结构和节点特征相似性 xff0c 然后使用注
  • GCC: Graph Contrastive Coding for Graph Neural Network Pre-Training

    摘要 目前图表示学习在许多任务上取得了很好的效果但是都是关注于具体领域的并不具有迁移性 本文借鉴预训练思想 xff0c 设计了一个自监督图神经网络框架来在多个网络中捕获一般化的网络拓扑结构属性 我们设计的预训练任务是在多个网络之间判别子图实
  • Graph Contrastive Learning with Adaptive Augmentation

    摘要 对比学习在无监督图表示学习中取得了很好的效果 xff0c 大部分图对比学习首先对输入图做随机增强生成两个视图然后最大化两个视图表示的一致性 其中 xff0c 图上的增强方式是非常重要的部分鲜有人探索 我们认为数据增强模式应该保留图固有
  • A Survey on Graph Structure Learning: Progress and Opportunities

    文章目录 摘要引言预备知识GSL pipline Graph Structure ModelingMetric based ApproachesNeural ApproachesDirect Approaches Postprocessin
  • 图构造总结-Graph‑based semi‑supervised learning via improving the quality of the graph dynamically

    前言 本博文主要对论文中提到的图构造方法进行梳理 xff0c 论文自己提出的模型并未介绍 xff0c 感兴趣的可以阅读原文 摘要 基于图的半监督学习GSSL主要包含两个过程 xff1a 图的构建和标签推测 传统的GSSL中这两个过程是完全独
  • 超图构造综述,Hypergraph Learning: Methods and Practices

    文章目录 摘要引言基础知识Hypergraph GenerationDistance based hypergraph generationRepresentation based hypergraph generationAttribut
  • 图论基础知识总结

    文章目录 图的概念路图的代数表示邻接矩阵可达矩阵完全关联矩阵拉普拉斯矩阵对称归一化拉普拉斯矩阵随机游走归一化拉普拉斯矩阵 欧拉图与汉密尔顿图平面图对偶与着色数与生成树最小生成树算法 xff1a 根树图的存储邻接矩阵邻接表十字链表邻接多重表
  • 图增强与图对比学习

    文章目录 对比学习数据增强基于特征的增强基于结构的增强基于采样的增强自适应的增强 代理任务同尺度对比跨尺度对比 目标函数参考 CSDN排版太垃圾了 xff0c 点此连接去知乎看吧 xff01 xff01 xff01 xff01 xff01
  • K-Core, K-Shell & K-Crust傻傻分不清楚

    K Core算法是用于在图中寻找符合一定紧密关系条件的子图结构的算法 xff0c 通常用于进行子图划分 xff0c 去除不重要的结点 参考论文k core Theories and applications ScienceDirect K
  • 社区发现算法总结

    图划分指将网络顶点划分为指定规模 xff0c 指定数量的非重叠群组 xff0c 使得群组之间的边数最小 图划分时 xff0c 群组的数量和规模是固定的 社区发现不同于图划分的是网络群组的数量和规模不是由实验者确定的 xff0c 而是由网络本
  • 机器学习面经--常见问题

    csdn的排版真的太垃圾了 xff0c 想看的移步知乎 1 xff0c Normalization 数据标准化处理主要包括数据同趋化处理和无量纲化处理两个方面 数据同趋化处理主要解决不同性质数据问题 xff0c 对不同性质指标直接加总不能正
  • 设计模式之创建型模式

    文章目录 创建型模式 Creational Pattern 1 1单例模式 Singleton Pattern 1 2工厂模式 Factory Pattern 1 3抽象工厂模式 Abstract Factory Pattern 1 4建造