前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >创建型模式(二)

创建型模式(二)

作者头像
每天学Java
发布2020-06-02 09:47:59
2740
发布2020-06-02 09:47:59
举报
文章被收录于专栏:每天学Java每天学Java

关于创建型模式中工厂方法模式,抽象工厂模式在上一篇文章中我们了解了一下,今天我们看一下单例模式,建造者模式,原型模式。

单例模式

单例模式我们用的很多,我想大家也都理解这种模式,就是保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

通常单例模式有5种实现方式:懒汉式;饿汉式;双检锁;静态内部类;枚举。个人推荐使用枚举,因为使用反序列化攻击和反射也不会创建新的对象出来,虽然其他实现方法也有办法避免这种攻击但是需要写一定量的代码

1、懒汉式 :必须加锁 synchronized 才能保证单例,但加锁会影响效率。

代码语言:javascript
复制
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

2、饿汉式 :类加载时就初始化,浪费内存。

代码语言:javascript
复制
public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}

3、双检锁/双重校验锁(DCL,即 double-checked locking)这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

代码语言:javascript
复制
public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

4、登记式/静态内部类。这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

代码语言:javascript
复制
public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}

5、枚举。这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

代码语言:javascript
复制
public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

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

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

建造者模式举例:去肯德基点餐,我们可以认为点餐就属于一个建造订单的过程。我们点餐的顺序是无关的,点什么东西也是没有要求的,可以单点,也可以点套餐,也可以套餐加单点,但是最后一定要点确认来完成订单。

代码语言:javascript
复制
public class OrderBuilder{
    private Burger mBurger;
    private Suit mSuit;

    //单点汉堡,num为数量
    public OrderBuilder burger(Burger burger, int num){
        mBurger = burger;
    }

    //点套餐,实际中套餐也可以点多份
    public OrderBuilder suit(Suit suit, int num){
    mSuit = suit;
    }

    //完成订单
    public Order build(){
        Order order = new Order();
        order.setBurger(mBurger);
        order.setSuit(mSuit);
        return order;
    }
}

另外适用于快速失败,在 build 时可以做校验,如果不满足必要条件,则可以直接抛出创建异常,在 OkHttp3 中的 Request.Builder 中就是这样用的。

代码语言:javascript
复制
public Request build() {  
    if (url == null) throw new IllegalStateException("url == null");  
    return new Request(this);
}

例如订单要求价格至少达到 30 块:

代码语言:javascript
复制
public class RequestBuilder{
    private final String mUrl;
    private Map<String, String> mHeaders = new HashMap<String, String>();

    private RequestBuilder(String url){
        mUrl = url;
    }

    public static RequestBuilder newBuilder(String url){
        return new RequestBuilder(url);
    }

    public RequestBuilder addHeader(String key, String value){
        mHeaders.put(key, value);
    }

    public Request build(){
        Request request = new Request();
        request.setUrl(mUrl);
        request.setHeaders(mHeaders);
        return request;
    }
}

另外,在构建时如果有必传参数和可选参数,可以为 Builder 类添加构造函数来保证必传参数不会遗漏,例如在构建一个 http 请求时, url 是必传的:

代码语言:javascript
复制
public class RequestBuilder{
    private final String mUrl;
    private Map<String, String> mHeaders = new HashMap<String, String>();

    private RequestBuilder(String url){
        mUrl = url;
    }

    public static RequestBuilder newBuilder(String url){
        return new RequestBuilder(url);
    }

    public RequestBuilder addHeader(String key, String value){
        mHeaders.put(key, value);
    }

    public Request build(){
        Request request = new Request();
        request.setUrl(mUrl);
        request.setHeaders(mHeaders);
        return request;
    }
}

原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

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

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

原型模式中有三个登场角色:

原型角色:定义用于复制现有实例来生成新实例的方法;

代码语言:javascript
复制
// 以贴主示例代码为例  
implements Cloneable   // 1.(抽象类或者接口)实现 java.lang.Cloneable 接口
public Shape clone();  // 2.定义复制现有实例来生成新实例的方法

具体原型角色:实现用于复制现有实例来生成新实例的方法

代码语言:javascript
复制
public Shape clone() {// 2.实现复制现有实例来生成新实例的方法(也可以由超类完成)
    Shape clone = null;
    try {
        clone = (Shape) clone();
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    return clone;
}

使用者角色:维护一个注册表,并提供一个找出正确实例原型的方法。最后,提供一个获取新实例的方法,用来委托复制实例的方法生成新实例。

代码语言:javascript
复制
private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();//维护一个注册表public static void loadCache() {
    Circle circle = new Circle();
    circle.setId("1");
    shapeMap.put(circle.getId(),circle);

    Square square = new Square();
    square.setId("2");
    shapeMap.put(square.getId(),square);

    Rectangle rectangle = new Rectangle();
    rectangle.setId("3");
    shapeMap.put(rectangle.getId(),rectangle);
}
public static Shape getShape(String shapeId) {//提供一个获取新实例的方法
    Shape cachedShape = shapeMap.get(shapeId);//提供一个找出正确实例原型的方法
    return (Shape) cachedShape.clone();//委托复制实例的方法生成新实例。
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例模式
  • 建造者模式
  • 原型模式
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档