Java设计模式-单例模式、观察者模式、工厂模式

单例设计模式

概念:

全局只有一个实例,自行实例化对象,自行向整个系统提供这个实例。

应用场景:
  • 需要全局只有一个实例的时候,如保存用户信息。
  • 只有一个访问途径
优点:
  • 全局只有一个实例,避免了频繁的创建实例,耗费的资源。
  • 提供了对唯一实例的受控访问。
  • 允许改变数目的实例。
缺点:
  • 单例模式没有抽象层,因此单例类扩展困难。
  • 单例职责过重。
  • 滥用单例可能造成其他问题,例如:持有上下文无法释放造成内存泄漏;实例化的对象长期未被使用,被回收导致对象状态丢失。
  • 单例实现的几种方式
饿汉式

类加载的时候就开始加载,使用的是静态变量,由JVM的classloader机制避免了线程安全问题,保证线程安全

缺点:一开始便加载占用内存,没有达到懒加载效果,如果实例化是耗费资源的,则懒加载可以节省加载时耗费的资源。另外如果实例一直没有使用会占用内存。

public class SingleTon{
    private static SingleTon single = new SingleTon();
    
    private SingleTon(){}
    
    public static SingleTon getInstanceO(){
        retrun single;
    }
}
饿汉式的另外方式

与正常的饿汉式并没有太大的区别。

public class SingleTon{
    private SingleTon instance = null;
    static{
        instance = new SingleTon();
    }
    private SingleTon(){}
    public static SingleTon getInstance(){
        return this.instance;
    } 
}
懒汉式

延迟加载,在调用getInstance的时候才开始加载,无须一直占用系统资源。从资源利用率的角度来讲优于饿汉式。

缺点:线程不安全,当线程A判断了是空的时候进行创建对象,在创建对象前线程B进来判断到是空,也创建了对象,因此线程A和线程B的对象不一致。

public class SingleTon {
    private static SingleTon single;
    
    private SingleTon(){}
    
    public static SingleTon getInstance(){
        if(single == null){
            single = new SingleTon();
        }
        return single;
    }
}

//优化---增加锁机制 1 ,在方法上加
public synchronize SingleTon getInstance(){
      if(single == null){
            single = new SingleTon();
        }
}
//缺点:锁住了整个类,这个类中的其他成员变量也需要等待释放锁后被其他线程使用,效率低下。
//优化,双重锁校验,缺点:可能会出现等待时间,降低系统性能。
public static SingleTon getInstance(){
    if(single == null){
        synchronize(SingleTon.class){
            if(single == null){
                single = new SingleTon();
            }
        }
    }
    return single;
}
静态内部类

静态内部类不是在一开始启动的时候加载,而是第一次调用的使用加载,实现了懒加载,并且由JVM的classloader机制实现线程同步,保证线程安全

虚拟机会保证一个类的构造器()方法在多线程环境中被正确地加载,同步,如果多个线程同时去初始化一个类,那么只有一个线程去执行这个类的.

public class SingleTon{
    private SingleTon();
    
    private static class SingleTonHelper{
        private static final SingleTon single = new SingleTon();
    }
    
    public static SingleTon getInstance(){
        retrun SingleTonHelper.single;
    }
}

观察者模式

概念:

实现一对多的依赖关系,当一方改变时,存在依赖关系的多方可以做出更改。

即发布订阅关系,发布者发布消息,存在订阅关系的订阅者可以接收消息。

包含的类
  • 抽象被观察者接口:定义被观察者需要实现的接口,如注册观察者建立关系;移除观察者,通知所有观察变化。
  • 抽象观察者接口:定义接收到消息后的更新方法。
  • 具体被观察者:抽象被观察者实现者,与观察者建立关系,并通知观察者的实现方法。
  • 具体观察者:被通知对象,具体实现收到通知后做出更新。
定义被观察者接口
public Interface IObservable{
    void registObserver(IObserver o);
    void removeObserver(IObserver o);
    void notifyObserver();
}
定义观察者接口
public Interface IObserver{
    void update(Strign message);  //传入的参数时任意想接收的消息
}
具体被观察者实现
public class MyObservable impelement IObservable{

	private String message ;//需要传递的消息
	private List<IObserver> observers ;
	
	public MyObservable(){
        observers = new ArrayList<>();
	}
    
    @override
    public void registObserver(IObserver o){
        if(observers!=null){
            observers.add(o);
        }
    }
    
    @override
    public void removeObserver(IObserver o){
        if(observers!=null && observers.size()>0){
            observers.remove(o);
        }
    }
    
    @override
    public void notifyObserver(){
        for(int i=0 ;i<observers.size();i++){
            observers.get(i).update(message);
        }
    }
    
    //需要更新的消息
    public void sendMsg(String msg){
        this.message = msg;
        //通知观察者
        notifyObserver();
    }
}
具体观察者
public class MyObserver impelement IObserver{
    @override 
    public void update(String message){
        System.out.println("接收到消息,开始处理");
    }
}

工厂模式

概念:

集中创建产品的类,是调用者和具体创建实例类分离开来,实现解偶

简单工厂模式

概念与步骤

又叫静态工厂模式,通过工厂类根据类型创建不同的实例类。

优点:结构简单,便于理解。客户不用关心具体的类的创建过程。

缺点:代码逻辑较其他工厂模式复杂,新增产品时必须修改工厂类。当需要创建的类比较多时,工厂类会变的较为臃肿。

//需创建的实例类的共同点
public interface Car{
    void go();
}
//具体实例
public class Audi{
    @override
    public void go(){
        System.out.println("奥迪在跑");
    }
}
public class Baoma{
    @override
    public void go(){
        System.out.println("奥迪在跑");
    }
}
//工厂类
public class CarFactory{
    public static final int AUDI_TYPR = 1;
    public static final int BMW_TYPR = 2;
    
    public static Car createCar(int type){
        Car car = null;
        switch(type){
            case AUDI_TYPR:
            	car = new Audi();
            case BMW_TYPR:
            	car = new Baoma();
        }
        return car;
    }
}

工厂方法模式

概念与步骤

把工厂类抽象出去,创建实例由具体的工厂类实现,针对每一个产品都由自己的具体工厂类实现。

优点:

调用者无需关心产品的实现,只需要关心产品的接口。增加新的产品时,只要接口不变,不需要修改工厂类的逻辑,实现解偶。

缺点:

类比较多,如果需要创建多个产品的时候项目结构会比较大。

//抽象工厂接口
public interface IFactory{
    Car createCar();
}
//具体工厂类
public class AudiFactory impelement IFactory{
    @Override
    public Car createCar(){
        return new Audi();
    }
}

//抽象产品
public interface Car{
    void getName();
}
//具体的产品
public class Audi impelement Car{
    @Override
    public void getName(){
        System.out.println("get an audi");
    }
}

//新增产品时新增产品类及产品工厂类

抽象工厂模式

概念与步骤

具有关联功能的产品作为一个产品族。 步骤:抽象工厂类,定于具体工厂类必须要实现的方法。

具体工厂类,创建一族产品;抽象产品类:定义产品的共性。具体产品类:创建具体的产品。

优点:具有工厂方法模式的优点外,另外可以在类内对产品族进行约束。

缺点:扩展比较麻烦。

试用场景:当创建的对象是一系列相互关联或相互依赖的产品族时适用。

//抽象工厂类
public interface AbstractFactory {
    AbstractCar createCar();
    AbstractPlane createPlane();
}
//抽象产品类
 public abstract class AbstractCar {
     public abstract void getName();
}

public abstract class AbstractPlane {
    public abstract void getName();
}
//具体工厂类
public class BigFactory implements AbstractFactory{
    @Override
    public AbstractCar createCar() {
        return new BigCar();
    }
    @Override
    public AbstractPlane createPlane() {
        return new BigPlane();
    }
}
//具体产品类
public class BigCar extends AbstractCar {

    @Override
    public void getName() {
        System.out.print("抽象工厂-大车");
    }
}
class BigPlane extends AbstractPlane {
    @Override
    public void getName() {
        System.out.print("抽象工厂-大飞机");
    }
}

demo地址:https://github.com/MarinaTsang/demo

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值