工厂模式+单例模式

大城市里の小女人 提交于 2019-12-22 00:45:46

工厂的三种模式:目的都是解耦

简单工厂

工厂是一个类:生产各种各样产品;不同类实现接口;业务全部在fractory中,违反了开闭原则。

 使用在业务简单的情况下。

工厂方法(如果工厂的产品全部属于同一个等级结构,则属于工厂方法。)

定义一个创建对象的工厂接口,让子类决定实例化哪一个类,将实际工作交给子类

例子:

工厂是一个接口,produceTrunk()  ,实现创建不同卡车类

卡车也是一个接口,实现不同卡车类

将不同卡车的业务逻辑抽离出fractory

优点

符合开闭原则,每增加一种产品,只需要增加相应具体的产品类和工厂子类。

符合单一职责原则,每个具体工厂类只负责创建对应的产品。

缺点

在增加一个新产品时,需要增加一个产品类和一个具体的子工厂,每个工厂生产一种产品,太过单一。

 

抽象工厂(如果工厂的产品来自多个等级结构,则属于抽象工厂模式)

抽象工厂角色:具体工厂必须时间的接口。

具体工厂角色:和具体业务逻辑相关的代码,创建对应的具体产品的对象。

抽象工厂:producetrunk();  producesedan();

具体工厂:宝马工厂(宝马轿车、宝马卡车)奥迪工厂(奥迪轿车、奥迪卡车)

抽象产品:卡车、轿车

具体产品:宝马卡车,宝马轿车,奥迪卡车,奥迪轿车

单例模式

概念:包含一个被称为单例的特殊类。

特点:单例类只能有一个实例;单例类必须自己创建自己的唯一实例;单例类必须给所有其他对象提供这一实例。

实现:private 构造类避免了外部类对此类进行实例化

场景需求

1.计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。

2.创建的一个对象需要消耗的资源过多,比如IO与数据库的连接等。

如何选择:

饿汉式是线程安全的,但是类加载就创建对象。如果在一个工厂模式下,缓存了很多实例,就得考虑效率问题,因为这个类一加载就把所有实例一起创建了(不管用不用);懒汉式优点是延时加载,缺点是需要用同步。看实际需求选择。

优点:在内存中只有一个实例,减少了内存开销,尤其是频繁创建和销毁实例(工具类);避免对资源的多重占用(比如写文件操作)

缺点:扩展很困难(private修饰的方法无法继承,不能再扩展)

饿汉式单例

在类加载初始化时就创建好一个静态的对象供外部使用,除非系统重启,这个对象不会改变,本身是线程安全的。

package single;
public class singlethon {
    //构造方法私有化
    singlethon() {}
    private static singlethon single=new singlethon();
    //对外提供调用
    public static singlethon getinstance() {
        return single;
    }
}

懒汉式单例

类加载的时候不创建对象,只有在使用的时候才创建,但是在多线程条件下,是线程不安全的。

package single;

import javax.sql.rowset.spi.SyncFactory;

public class single2 {
    private single2() {}
    private static single2 single=null;
    //同步锁,一个线程执行时,其他线程处于等待
    synchronized public static single2 getinstance() {
        if(single==null) {
            //线程不安全
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            single=new single2();
        }
        return single;
    }
}
//多线程,CPU 交替执行有先后

可以用同步锁解决线程不安全问题,但是加锁会降低效率;为提高效率,减小代码同步范围。但是用了双重检索,也不一定是线程安全的,因为还有系统指令重拍,此时可以将对象用volatile修饰。

package single;

import javax.sql.rowset.spi.SyncFactory;

public class single2 {
    private single2() {}
    private static single2 single=null;
    //同步锁,一个线程执行时,其他线程处于等待
     public static single2 getinstance() {
        //双重检索
             if(single==null) {
                    //线程不安全
                 synchronized(single2.class) {
                     if(single==null) {
                         single=new single2();
                     }
                } 
             }
        return single;
    }
}
//多线程,CPU 交替执行有先后

静态内部类

package single;
public class single3 {
    private single3() {}
    //外部类被加载,内部类没有被加载,除非主动使用
    private static class insideclass {
        private static single3 single=new single3();
    }
    
    public static single3 getinstance() {
        return insideclass.single;
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!