Padrão de design_singleton (singleton)

Padrão de design_singleton (singleton)

Modo Singleton: Apenas uma instância pode ser criada e uma instância é suficiente para negócios de desenvolvimento. Neste caso, é recomendado usar o modo singleton.
Tais como: classe de ferramenta, classe de recurso.

1. Como escrever o modo singleton
O modo singleton inclui homem preguiçoso, homem faminto, enumeração, classe interna estática e bloqueio de verificação dupla.
Aqui escrevo apenas sobre dois deles comumente usados: homem faminto e classe interna estática. Os que os acompanham serão comparados com alguns outros, mas certamente não serão abrangentes.
Este método
evita problemas de sincronização multi-thread com base no mecanismo classloder. No entanto, a instância é instanciada quando a classe é carregada. No modo singleton, a maioria dos métodos chama o método getInstance. Neste momento, a instância inicializada obviamente não alcance o efeito de carregamento lento (carregamento lento). Isto é adequado para situações onde a classe precisa ser carregada desde o início

public class Car {
    private static final Car car = new Car();

    private Car(){}

    public static  Car getInstance(){
        return car;
    }

    public void driveCar(int index){
        System.out.println("驾驶员已经启动"+index+"汽车");
    }
}

Para comparar, você pode observar a maneira de escrever classes internas estáticas. O método
de classe interna estática
também usa o mecanismo classloder para garantir que haja apenas um thread ao inicializar a instância. É diferente do método faminto (uma diferença muito sutil ): o método faminto O método é que, enquanto a classe Singleton estiver carregada, a instância será instanciada (o efeito de carregamento lento não é alcançado).Neste método, a classe Singleton é carregada e a instância não é necessariamente inicializada . Como a classe SingletonHolder não é usada ativamente, a classe SingletonHolder só será carregada explicitamente chamando o método getInstance para instanciar a instância. Imagine se instanciar uma instância consome recursos e eu quero que ela seja carregada lentamente. Por outro lado, não quero instanciar quando a classe Singleton é carregada, porque não posso garantir que a classe Singleton possa ser usada ativamente em outros places. está carregado, então é obviamente inapropriado instanciar a instância neste momento. Neste momento, este método parece muito razoável em comparação com o método do homem faminto.

public class CarStaticClass {
    private static class CarStaticClassHolder{
        private static CarStaticClass car = new CarStaticClass();
    }
    private CarStaticClass(){};

    public static final CarStaticClass getInstance(){
        return CarStaticClassHolder.car;
    }
}

Os dois acima são as formas de escrita mais comumente usadas. Aqui estou escrevendo sobre o jeito do homem preguiçoso e algumas coisas para prestar atenção no jeito do homem preguiçoso.
Método preguiçoso (thread inseguro)
.Geralmente, vários objetos serão criados quando vários threads o chamam ao mesmo tempo. Obviamente, o propósito de um singleton não é alcançado. Porque Car está vazio quando chamado por um thread (A). O carro também fica vazio quando chamado por outro thread (B). Então dois objetos Car serão criados ao mesmo tempo. Ou seja, dois objetos Car são retornados. Portanto, esta forma de escrever geralmente falha em atingir o propósito de Singleton. Mas é obviamente um carregamento lento, mas só pode ser passado devido à insegurança do thread.

/*实例化类*/
public class Car {
    
    
    private static Car car;

    private Car(){}

    public static synchronized Car getInstance(){
        if(car == null){
            System.out.println("创建Car对象");
            car = new Car();
        }
        return car;
    }

    public void driveCar(int index){
        System.out.println("驾驶员已经启动汽车");
    }
}

/*========================================*/
/*调用类这里可以看出多线程的方式调用。代码都比较简单就没写注释了*/
public class Client extends Thread{
    
    

    public void run(){
        for(int i =0 ;i<5; i++){
            Car car = Car.getInstance();
            car.driveCar(i);
        }
    }


    public static void main(String args[]){
        Client client1 = new Client();
        Client client2 = new Client();
        client1.start();
        client2.start();
    }
}

/*========================================*/
/*运行结果*/
创建了Car
创建了Car
驾驶员已经启动0汽车
驾驶员已经启动0汽车
驾驶员已经启动1汽车
驾驶员已经启动2汽车
驾驶员已经启动3汽车
驾驶员已经启动4汽车
驾驶员已经启动1汽车
驾驶员已经启动2汽车
驾驶员已经启动3汽车
驾驶员已经启动4汽车

Lazy (thread-safe)
tem poucas alterações de código em comparação com thread-insafe e adiciona um bloqueio. Também tem o efeito de carregamento lento. Mas o que estou dizendo é que esse método é muito ineficiente.

public class Car {
    private static final Car car = new Car();

    private Car(){}

    public static synchronized  Car getInstance(){
        return car;
    }

    public void driveCar(int index){
        System.out.println("驾驶员已经启动"+index+"汽车");
    }
}

Quanto às outras formas. Parece raramente ser visto no trabalho real. Aqui estão apenas algumas instruções simples. O método de enumeração é relativamente raro, acho que sua principal função é evitar que a desserialização recrie novos objetos. Se houver um requisito de instanciação, a interface de serialização poderá ser implementada.
Não acho que o método de bloqueio de verificação dupla seja necessário. Se não for uma ocasião específica, não há necessidade de usar o bloqueio de verificação dupla. Para obter detalhes, consulte
2. Explicação de
por que o modo singleton pode se tornar um singleton.Pode não ser muito diferente se o código for normal. Caros amigos, vejam o método de construção do padrão singleton, seu método de construção é sem parâmetros e privado. Isso garantirá que objetos externos não possam ser criados por meio de novos. Só pode ser construído através do método getInstance. Neste método está o objeto retornado, que foi inicializado. E é final e estático. Nenhum novo objeto será gerado desta forma.
Quanto a usar Hungry Man ou classes internas estáticas, isso depende do cenário. Geralmente, Hungry é usado, a menos que classes internas estáticas sejam usadas explicitamente. Certifique-se de garantir a segurança da linha ao usá-la.

Acho que você gosta

Origin blog.csdn.net/my_God_sky/article/details/52201222
Recomendado
Clasificación