设计模式—创建型模式

本文详细介绍了创建型设计模式,包括单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式。单例模式确保类只有一个实例,适用于全局访问点和资源管理。工厂模式提供了一个创建对象的接口,简化了对象创建过程。抽象工厂模式用于创建一系列相关或相互依赖的对象。建造者模式通过步骤构建复杂对象,提供了更大的灵活性。原型模式通过克隆已有对象创建新对象,适用于性能优化和逃避构造函数约束。每种模式都分析了其优缺点和应用场景。

1、创建型模式

    创建型模式的作用就是为了产生实例对象。

1.1、单例模式


定义:一个类只有一个实例,且这个类能自行创建这个实例。

特点:1、单例类只有一个对象

           2、单例类必须自己创建自己的对象

           3、单例类需要给其他类提供访问这个对象的节点

应用:Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等。

优点:内存中只有一个实例;避免对资源的多重占用;设置全局访问节点,可以优化资源的访问。

缺点:不能继承,扩展困难;并发测试中,不利于代码调试。


单例类的结构

单例类的实现

(1)懒汉式实现

public class LazySingleton {
    private static volatile LazySingleton instance = null;    //保证 instance 在所有线程中同步

    private LazySingleton() {
    }    //private 避免类在外部被实例化

    public static synchronized LazySingleton getInstance() {
        //getInstance 方法前加同步
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

    懒汉式实现在实例化时没有生成单例,只有在调用getInstance()时才生成单例。懒汉式需要保证多线程安全性(通过volatile和synchronized),但带来而外的开销。

(2)饿汉式单例

public class HungrySingleton {
    private static final HungrySingleton instance = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return instance;
    }
}

    饿汉式单例在实例化时就生成单例,是线程安全的。


参考文献

(1)菜鸟教程-单例模式

(2)C语言中文网-单例模式


1.2、工厂模式

定义:在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

示例:


1.3、抽象工厂模式

定义:抽象工厂模式(Abstract Factory Pattern)是围绕一个抽象工厂创建其他工厂,该抽象工厂又称为其他工厂的工厂。

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

示例:


1.4、建造者模式

定义:建造者模式(Builder Pattern)使用多个简单的对象一步一步(链式)构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

优点: 1、建造者独立,易扩展。 2、便于控制细节风险。

缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。

示例:

class User {
    // 下面是“一堆”的属性
    private String name;
    private String password;
    private String nickName;
    private int age;

    // 构造方法私有化,不然客户端就会直接调用构造方法了
    private User(String name, String password, String nickName, int age) {
        this.name = name;
        this.password = password;
        this.nickName = nickName;
        this.age = age;
    }
    // 静态方法,用于生成一个 Builder,这个不一定要有,不过写这个方法是一个很好的习惯,
    // 有些代码要求别人写 new User.UserBuilder().a()...build() 看上去就没那么好
    public static UserBuilder builder() {
        return new UserBuilder();
    }

    public static class UserBuilder {
        // 下面是和 User 一模一样的一堆属性
        private String  name;
        private String password;
        private String nickName;
        private int age;

        private UserBuilder() {
        }

        // 链式调用设置各个属性值,返回 this,即 UserBuilder
        public UserBuilder name(String name) {
            this.name = name;
            return this;
        }

        public UserBuilder password(String password) {
            this.password = password;
            return this;
        }

        public UserBuilder nickName(String nickName) {
            this.nickName = nickName;
            return this;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        // build() 方法负责将 UserBuilder 中设置好的属性“复制”到 User 中。
        // 当然,可以在 “复制” 之前做点检验
        public User build() {
            if (name == null || password == null) {
                throw new RuntimeException("用户名和密码必填");
            }
            if (age <= 0 || age >= 150) {
                throw new RuntimeException("年龄不合法");
            }
            // 还可以做赋予”默认值“的功能
              if (nickName == null) {
                nickName = name;
            }
            return new User(name, password, nickName, age);
        }
    }
}

则可以通过下面的代码进行调用:

        User d = User.builder()
                .name("foo")
                .password("pAss12345")
                .age(25)
                .build();

Tips:可以通过LomBok的注解:@Builder将类设置为建造者模式

@Builder
class User {
    private String  name;
    private String password;
    private String nickName;
    private int age;
}

1.5、原型模式

定义:原型模式(Prototype Pattern)是用于创建重复的对象,首先需要一个原型实例,基于这个原型实例产生新的实例,也就是“克隆”。

优点: 1、性能提高。 2、逃避构造函数的约束。

缺点: 1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。 2、必须实现 Cloneable 接口。

Tips:Object 类中有一个 clone() 方法,它用于生成一个新的对象,当然,如果我们要调用这个方法,java 要求我们的类必须先实现 Cloneable 接口,此接口没有定义任何方法,但是不这么做的话,在 clone() 的时候,会抛出 CloneNotSupportedException 异常。同时,java 的克隆是浅克隆,碰到对象引用的时候,克隆出来的对象和原对象中的引用将指向同一个对象。通常实现深克隆的方法是将对象进行序列化,然后再进行反序列化。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值