大家好,我是老唐。今天给同学们带来的是Java设计模式的简单讲解。
OK,今天带给大家的是本帅的浴照,希望大家把持住。
什么是设计模式呢?在我的理解里就是 先人们在敲代码时的总结,就是在解决代码问题以及提高代码质量的一系列套路,这就被称为设计模式。
设计模式的六大原则:开闭原则,里氏代换原则,依赖倒转原则,接口隔离原则,迪米特法则,合成复用原则。
我们今天说的是设计模式中最常见的几种。
优点:线程安全、执行效率比较高。
缺点:所有对象类加载的时候就实例化。浪费内存资源。
我们这里通过把构造器私有化,在外部我们就没有办法去new一个对象,只能通过getInstance()方法获取,我们这里也能看到h1和h2通过getInstance()获取的对象是同一个对象。
优点:资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
缺点:第一次加载时不够快,多线程使用不必要的同步开销大
懒汉模式在单线程没有问题,在多线程就可能会出现多个对象的情况,为了避免这种情况的发生,就出现了双重检验模式。
优点:线程安全,且效率高的。
缺点:并不能保证它会在单处理器或多处理器计算机上顺利运行。
第一次判断是否为null:
第一次判断是在Synchronized同步代码块外,理由是单例模式只会创建一个实例,并通过getInstance方法返回singleton对象,所以如果已经创建了singleton对象,就不用进入同步代码块,不用竞争锁,直接返回前面创建的实例即可,这样大大提升效率。
第二次判断singleton是否为null:
第二次判断原因是为了保证同步,假若线程A通过了第一次判断,进入了同步代码块,但是还未执行,线程B就进来了(线程B获得CPU时间片),线程B也通过了第一次判断(线程A并未创建实例,所以B通过了第一次判断),准备进入同步代码块,假若这个时候不判断,就会存在这种情况:线程B创建了实例,此时恰好A也获得执行时间片,如果不加以判断,那么线程A也会创建一个实例,就会造成多实例的情况。
优点:线程安全,利用静态内部类特点实现延迟加载,效率高。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
优点:线程安全,调用效率高,不能延时加载
缺点:不可继承。
通过提供序列化和线程安全并且几行代码搞定,说明枚举单例模式是java5之后创建单例最好的方法。
使用步骤
创建抽象产品类 , 定义具体产品的公共接口
创建具体产品类(继承抽象产品类),定义生产的具体产品
创建工厂类,通过创建静态方法根据传入不同参数从而创建不同具体产品类的实例
外界通过调用工厂类的静态方法,传入不同参数从而创建不同具体产品类的实例
应用场景:客户如果只知道传入工厂类的参数,对于如何创建对象的逻辑不关心时,当工厂类负责创建的对象(具体产品)比较少时。
(2)工厂方法模式
使用步骤
创建抽象工厂类和抽象产品类
创建具体产品类和具体工厂类继承抽象类
外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
应用场景:
1 当一个类不知道它所需要的对象的类时
在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可;
2 当一个类希望通过其子类来指定创建对象时
在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
3 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
使用步骤:
创建产品接口跟具体产品
创建工厂接口跟具体工厂
测试
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口
原型模式,在java中使用浅克隆时,当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制;而使用深克隆时,除了对象本身被复制外,对象所包含的所有成员变量也将被复制。
浅克隆: 被Clone的对象的所有变量都含有原来对象相同的值,而引用变量还是原来对用的引用
使用步骤
创建两个类,第二个类实现Cloneable接口并重写Clone()方法并且把第一个类传入。
测试
使用步骤
创建两个类实现Serializable接口
测试
原型模式适合于当一个类初始化需要消耗很多资源时,有很多相似对象时,可以设计一个原型,通过对成员变量的些微修改来实现;需要时可以用深克隆的方式保存对象的状态,比如实现撤销操作等。
优点:真实角色也就是业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
使用步骤
创建一个接口,再用另外一个类去实现这个接口
创建一个代理类
测试
使用jdk的反射机制,创建对象的能力, 创建的是代理类的对象。
使用步骤
创建一个接口,再用类去实现这个接口
测试
好的,这里我们看见简哥去洗个一次接近13米的jio。
使用步骤
创建接口,以及实现接口的实体类
创建实现了 Shape 接口的抽象装饰类。
创建扩展了 ShapeDecorator 类的实体装饰类。
使用 RedShapeDecorator 来装饰 Shape 对象。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
好了,这期的代码就到这里了,希望对同学们有所帮助。咱们下期见。