首页 > 其他分享 >设计模式 (1): 5 种创建型模式 (结合代码详解)

设计模式 (1): 5 种创建型模式 (结合代码详解)

时间:2023-10-08 23:44:25浏览次数:33  
标签:return 代码 class 详解 static 单例 Vehicle 设计模式 public


目录


1 单例模式

需考虑的问题:

  • 是否线程安全
  • 是否延迟创建
  • 有无破坏单例的方法

饿汉单例

public class _01Eager {
    // 不延迟单例
    // 类初始化时创建单例
    private static final _01Eager instance = new _01Eager();
    private _01Eager(){}
    public static _01Eager getInstance(){
        return instance;
    }
}

懒汉单例

public class _02Lazyer {
    // 方法延迟单例
    // 相比于 饿汉式,把 instance 的创建
    // 从 类初始化时 移动到 方法调用时
    private static _02Lazyer instance;
    private _02Lazyer(){}
    public static synchronized _02Lazyer getInstance(){
        if(instance == null)
            instance = new _02Lazyer();
        return instance;
    }
}

双重检验单例

public class _03DoubleCheck {
    // 方法延迟单例
    // 相比 懒汉式,缩小锁粒度
    private static _03DoubleCheck instance;
    private _03DoubleCheck(){}
    public static _03DoubleCheck getInstance(){
        if(instance == null){
            synchronized (_03DoubleCheck.class){
                if(instance == null) {
                    instance = new _03DoubleCheck();
                }
            }
        }
        return instance;
    }
}

静态内部类单例

public class _04Static implements Serializable {
    private static class Static {
        private final static _04Static instance = new _04Static();
    }
    private _04Static(){}
    public static _04Static getInstance(){
        return Static.instance;
    }
}

破坏单例 (反射、反序列化)

(导入序列化工具依赖:org.apache.commons.commons-lang3

public class StaticAttack {
    StaticAttack(){}
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 测试 反射和反序列化 破坏 静态内部类
        staticAttack();
    }
    public static void staticAttack() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 单例对象
        _04Static obj = _04Static.getInstance();
        isSingleton(obj, _04Static.getInstance()); // true
        // 测试是否可以破坏单例
        _04Static newObj1, newObj2;
        // 反射创建 新对象 可以破坏单例
        Constructor<_04Static> constructor = _04Static.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        newObj1 = constructor.newInstance();
        isSingleton(obj, newObj1); // false
        // 反序列化创建 新对象 可以破坏单例
        byte[] serialize = SerializationUtils.serialize(obj);
        newObj2 = SerializationUtils.deserialize(serialize);
        isSingleton(obj, newObj2); // false
    }
    public static void isSingleton(Object obj1, Object obj2){
        System.out.println("是否是单例? " + (obj1 == obj2));
    }
}

枚举类单例

// 枚举类可以避免 反射 和 反序列化 破坏单例
public enum _05Enum {
    SINGLETON;
    // 单例的方法
    public String doSomething(){
        return "处理结束";
    }
}
// 调用单例的方法
_05Enum.SINGLETON.doSomething();

2 工厂模式

简单工厂模式

  • 消费者:依赖 商店
  • 商店:依赖 工厂,返回 具体产品
  • 工厂:if - else 地创建 具体产品
  • 产品:产品种类 通过 实现 很多抽象产品(接口)
public class sf {
    // 抽象产品类 Vehicle
    interface Vehicle {}
    // Vehicle 的 具体产品
    static class Car implements Vehicle {
        public String toString() {
            return "Car";
        }
    }
    static class Bike implements Vehicle {
        public String toString() {
            return "Bike";
        }
    }
    // 所有具体产品 都共用 抽象产品的工厂
    static class VehicleFactory {
        Vehicle createVehicle(String type){
            if(type == null)
                return null;
            Vehicle vehicle = null;
            if(type.equalsIgnoreCase("Car"))
                vehicle = new Car();
            else if(type.equalsIgnoreCase("Bike"))
                vehicle = new Bike();
            return vehicle;
        }
    }
}

工厂方法模式

public class fm {
    // 抽象产品类 Vehicle
    interface Vehicle {}
    // Vehicle 的 具体产品
    static class Car implements Vehicle {
        public String toString() {
            return "Car";
        }
    }
    static class Bike implements Vehicle {
        public String toString() {
            return "Bike";
        }
    }
    // Vehicle 的 抽象工厂
    static abstract class VehicleFactory {
        abstract Vehicle createVehicle();
    }
    // *继承* 抽象工厂
    // 一个具体产品 对应 一个具体工厂
    static class CarFactory extends VehicleFactory {
        Vehicle createVehicle(){
            return new Car();
        }
    }
    static class BikeFactory extends VehicleFactory {
        Vehicle createVehicle() {
            return new Bike();
        }
    }
}

3 抽象工厂模式

代码实现

public class af {
    // 抽象工厂用于产品族
    // 产品族 和 各自的抽象工厂
    interface Vehicle {}
    interface Accessory {}
    // interface Engine {} 产品族拓展的例子
    interface VehicleFactory {
        Vehicle createVehicle();
    }
    interface AccessoryFactory {
        Accessory createAccessory();
    }
    // interface EngineFactory { Engine createEngine();}

    // Vehicle 的 具体产品
    static class Car implements Vehicle {
        public String toString() {
            return "Car";
        }
    }
    static class Bike implements Vehicle {
        public String toString() {
            return "Bike";
        }
    }
    // Accessory 的具体产品
    static class CarAccessory implements Accessory {
        public String toString() {
            return "CarAccessory";
        }
    }
    static class BikeAccessory implements Accessory {
        public String toString() {
            return "BikeAccessory";
        }
    }
    // 每 *实现* 一个接口,产品族就拓展一类产品
    // 产品族工厂 实现了 多个接口,实现产品族的可拓展性
    static class CarFactory implements
            VehicleFactory, AccessoryFactory //,EngineFactory
    {
        public Vehicle createVehicle() {
            return new Car();
        }
        public Accessory createAccessory() {
            return new CarAccessory();
        }
    }
    static class BikeFactory implements
            VehicleFactory, AccessoryFactory //,EngineFactory
    {
        public Vehicle createVehicle() {
            return new Bike();
        }
        public Accessory createAccessory() {
            return new BikeAccessory();
        }
    }
}

对比三种工厂模式

| 简单工厂模式:
- A 产品:A1 - A2
	 简单工厂
	/ if-else \ 
  A1           A2 

| 工厂方法模式:
- A 产品:A1 - A2
      A 抽象工厂(抽象类)
      - 生产 A
     /  继承   \
 A1 具体工厂   A2 具体工厂
 - 生产 A1     - 生产 A2

| 抽象工厂模式:
- (A, B, ...) 产品* 族 *:A1 - A2 | B1 - B2 | C ..
 A 抽象工厂(接口)   B 抽象工厂(接口)   C 抽象工厂
 - 生产 A (接口)    - 生产 B (接口)
        \     多实现     /
      (A1, B1) 具体产品族工厂
	   - 生产 A1 (实现接口)
	   - 生产 B1 (实现接口)

可以看到,抽象工厂可以实现最复杂的功能,但是在简单情形下增加了复杂性

如何选择工厂方法和抽象工厂?

在实际应用中,需要根据具体的需求和场景选择合适的模式:

  • 如果产品种类较少,可以使用工厂方法模式
  • 如果产品种类较多,形成了产品族(并且 产品族 有可能 增删 产品),可以使用抽象工厂模式

4 建造者模式

5 原型模式

标签:return,代码,class,详解,static,单例,Vehicle,设计模式,public
From: https://www.cnblogs.com/luoyicode/p/17750157.html

相关文章

  • git未提交代码提交到别的分支
    未创建新分支,修改过代码,将代码提交到新分支步骤1:在当前的develop分支上的修改暂存起来gitstash步骤2:暂存修改后,在本地新建分支(develop_backup为新分支的名字)gitcheckout-bstage_2步骤3:将暂存的修改放到新建分支中gitstashpop步骤4:使用命令进行常规的add、commit步......
  • Python信贷风控模型:梯度提升Adaboost,XGBoost,SGD, GBOOST, SVC,随机森林, KNN预测金
    原文链接:http://tecdat.cn/?p=26184 原文出处:拓端数据部落公众号最近我们被客户要求撰写关于信贷风控模型的研究报告,包括一些图形和统计输出。在此数据集中,我们必须预测信贷的违约支付,并找出哪些变量是违约支付的最强预测因子?以及不同人口统计学变量的类别,拖欠还款的概率如何......
  • 数据分享|Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖
    原文链接:http://tecdat.cn/?p=23518最近我们被客户要求撰写关于银行拉新活动的研究报告,包括一些图形和统计输出。项目背景:银行的主要盈利业务靠的是贷款,这些客户中的大多数是存款大小不等的责任客户(存款人)。银行拥有不断增长的客户该银行希望增加借款人(资产客户),开展更多的贷款......
  • 万字长文详解Java线程池面试题
    王有志,一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群:共同富裕的Java人今天是《面霸的自我修养》第6篇文章,我们一起来看看面试中会问到哪些关于线程池的问题吧。数据来源:大部分来自于各机构(Java之父,Java继父,某灵,某泡,某客)以及各博主整理文档;小部分来自于......
  • Go 语言代码简单的在线购物平台:
    以下是一个相对复杂的Go语言代码示例,用于实现一个简单的在线购物平台:packagemainimport( "fmt")typeUserstruct{ IDint Namestring Emailstring Passwordstring Addressstring}typeProductstruct{ IDint Namestring Priceflo......
  • 9月份读后感1——《代码大全2》
    作为一名大二软件工程学生,我深刻认识到学习的重要性,尤其是对于编程和开发能力的提升。通过阅读《代码大全2》,我不仅对代码质量的重要性有了更深刻的认识,还学到了许多高效学习的方法和技巧。首先,我认识到高效学习是提升编程和开发能力的关键。在过去的学习过程中,我常常陷入被动地......
  • 9月份读后感2——再读《代码大全2》
    作为一名大二学生,我再次阅读《代码大全2》给我带来了不同的启发和收获。首先,与第一次阅读相比,我更深刻地理解了书中强调的实践的重要性。在大二的学习中,我有更多的机会参与到实际项目中,通过编写代码、解决问题,不断提升自己的实践能力。通过实践,我能够更好地理解书中的概念和方法,......
  • 《代码大全》阅读笔记04
    关键的“构建”决策,阅读了第四章之后,收获很多,具体内容如下:在真正构建之前,需要进行一些决策,首先是要选择语言,这貌似是一个难题,而且很有争议,其实对于具体程序员来说却不是一个问题,你几乎没啥选择权,老板让你用啥你就用啥吧,对新手来说,你会什么就找什么样的工作就是了,对于老手来说,公司......
  • 【愚公系列】2023年10月 二十三种设计模式(七)-桥接模式(Bridge Pattern)
    ......
  • Tarjan强连通分量详解
    1、简介:在阅读下列内容之前,请务必了解 图论相关概念 中的基础部分。强连通的定义是:有向图G强连通是指,G中任意两个结点连通。强连通分量(StronglyConnectedComponents,SCC)的定义是:极大的强连通子图。这里要介绍的是如何来求强连通分量。2、引入:在介绍该算法之前,先来了解......