精华内容
参与话题
问答
  • Java常见设计模式

    2019-06-20 16:44:00
    Java常见设计模式包括:单例模式,工厂模式,抽象工厂模式,命令模式,职责链模式,代理模式等。 1.单例模式: 定义:在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例...

    Java常见设计模式包括:单例模式,工厂模式,抽象工厂模式,命令模式,职责链模式,代理模式等。

    1.单例模式:
    定义:在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。
    简单实现:

    public class Singleton{
        private static Singleton singleton;
    
        private Singleton() {
        }
    
        public synchronized static Single newInstance() {
            if (singleton== null) {
                singleton= new Singleton();
            }
            return singleton;
        }
    }
    

    2.工厂模式:
    工厂模式是用来创建对象的一种最常用的设计模式。

    3.抽象工厂模式

    4.命令模式

    5.职责链模式
    将能够处理同一类请求的对象连成一条链,使这些对象都有机会处理请求,所提交的请求沿着链传递。从而避免请求的发送者和接受者之间的耦合关系。链上的对象逐个判断是否有能力处理该请求,如果能则就处理,如果不能,则传给链上的下一个对象。

    直到有一个对象处理它为止。

    6.代理模式

    展开全文
  • java常见设计模式

    2018-08-26 11:40:00
    工厂模式 普通工厂模式,就是建立一个工厂类,...工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,...

    工厂模式

    普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

    多个工厂模式,编写多个创建工厂的方法即可。

    静态工厂模式,在多个工厂模式的基础上把Factory种方法的返回值标明位静态即可。

    抽象工厂模式

    工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

    抽象工厂模式和普通工厂模式不同的地方在于抽象工厂模式是创建多个工厂类且这些工厂都实现同一个借口Provide(借口中有方法produce()),而普通工厂模式中只有一个工厂类。

    单例模式

    单例模式中必须有三个东西:单例对象,编写的无参构造方法,用于返回单例对象的getInstance()方法。

    单例模式的定义就是:“一个类有且仅有一个实例, 并且自行实例向整个系统提供”。

    volatile的作用就是确保本条指令不会因编译器的优化而省略,且要求每次直接读值。

    不管使用的是哪种单例模式,里面的单例对象都是静态变量。

    单例模式有三种编写方式。

    较为正规的就是双重锁模式:

    public class Singleton {
        private Singleton()
        {
            
        }
        private static volatile Singleton instance = null;
        public static Singleton getInstance()
        {
            if(instance == null)
            {
                synchronized(Singleton.class)
                {
                    if(instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

    然后还有懒汉模式,懒汉模式是不需要使用双重锁的,性能较低,直接把锁加在方法上。

    public class Singleton {
        private static Singleton instance = null;
        private Singleton()
        {
            
        }
        public static synchronized Singleton getInstance()
        {
            if(instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }

    饿汉模式,单例模式的创建更为简单。直接创建静态常量单例对象,不可以改变,连创建都省掉了。

    public class Singleton {
        private static final Singleton instance = new Singleton();
        private Singleton()
        {
            
        }
        public Singleton getInstance()
        {
            return instance;
        }
    }

     

    转载于:https://www.cnblogs.com/liaoxiaolao/p/9536751.html

    展开全文
  • Java 常见设计模式

    2010-01-29 17:30:00
    常用的设计模式分为如下 23 种模式:Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。Adapter:将一个类的接口转换成客户希望的另一个接口,使得原来由于接口不兼容而不能...

    常用的设计模式分为如下 23 种模式:
    Abstract Factory:
    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它 们具体的类。
    Adapter:
    将一个类的接口转换成客户希望的另一个接口,使得原来由于接口不兼容而不能一起工作的那些类可以一起工作。
    Bridge:
    将 抽象部分与它的实现部分分离,使之可以独立变化。
    Chain of Responsibility:
    为解除请求的发送者和接收者之间的耦 合,而使多个对象有机会处理这个请求。将这些请求连成一个链,并沿着这条链传递该请求,直到有个对象处理它。
    Command:
    将一个请求 封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可以取消的操作。
    Composite:
    将 对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得客户对单个对象和复合对象的使用具有一致性。
    Decorator:
    动 态地给一个对象添加一些额外的职责。就扩展功能而言,Decorator模式比生成子类方式更加灵活。
    Facade:
    为子系统中的一组接 口提供一个一致的界面,Facade模式定义了一个高层接口,使得这个子系统更加容易使用。
    Factory Method:
    定义一个用于 创建对象的接口,让子类决定将哪一个类实例化。Factory Method让一个类的实例化延迟到子类。
    Flyweight:
    运用共享 技术有效的支持大量细粒度的对象。
    Interpreter:
    给定一个语言,定义它的文法的一种表示,并定义一个解释器用于解释特定文法。
    Iterator:
    提 供一种方法顺序访问一个聚合对象中的各种元素,而无需暴露该对象的内部表示。
    Mediator:
    用一个中介对象来封装一系列的对象交互。 中介者使各对象不需要显式相互引用,从而使得耦合松散,可以独立改变相互之间的交互。
    Memento:
    不破坏封装的前提下,捕获对象的内 部状态,并在该对象之外保存这个状态。
    Observer:
    定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生变化时依赖于它的 所有的对象都得到通知和刷新。
    Prototype:
    用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
    Proxy:
    为 其他对象提供一个代理以控制对这个对象的访问。
    Singleton:
    保证一个类仅有一个实例,并提供一个访问它的全局点。
    State:
    允 许一个对象再内部状态改变的时候改变它的行为。对象看起来似乎修改了所属的类。
    Strategy:
    定义一系列的算法,把他们封装起来,并 可以相互替换,使算法独立于客户。
    Template Method:
    定义一个操作中的算法骨架,而将这些算法的具体实现的代码延迟到子类 中完成。
    Visitor:
    标识一个作用于某对象结构中的各元素的操作,在不改变各元素的类的前提下定义作用于这个元素的新操作。

    展开全文
  • java常见设计模式之---单例模式1、单例模式简介应用场景举例2、单例模式的特点3、单例模式和静态类4、单例模式的经典实现饱汉式单例创建饿汉式单例创建,五种方法0)、不完美的饿汉式(非线程安全)1)、同步延迟加载 ...

    1、单例模式简介

    单例模式(Singleton Pattern)是一个比较简单的模式,其原始定义如下:Ensure a class has only one instance, and provide a global point of access to it. 即确保只有一个实例,而且自行实例化并向整个系统提供这个实例。

    因程序需要,有时我们只需要某个类只保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。事实上,这些应用都或多或少具有资源管理器的功能。

    总之,选择单例模式就是为了避免不一致状态。

    应用场景举例

    1)、spring中的单例模式:在spring中每个bean都是单例的,这样做的好处是Spring容器可以管理这些bean的生命周期,由spring容器来决定实例的创建、销毁、销毁后的处理等等问题。如果采用非单例模式,则Bean初始化后的管理交给J2EE容器了,Spring容器就不在跟踪管理Bean的生命周期了。

    2)、多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。。

    3)、操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。

    4)、应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加

    5)、Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源

    2、单例模式的特点

    包括下面几个部分的简单记忆”3125

    3和1一起记忆,即三个一

    • 单例模式只能有一个实例,
    • 单例类必须创建自己的唯一实例
    • 单例类必须向其他对象提供这一实例

    综上所述,单例模式就是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种方法。

    2即是指2种实现方式:懒汉式和 饿汉式
    5即是指五种经典实现

    有两种场景可能导致非单例的情况

    场景一:如果单例由不同的类加载器加载,那便有可能存在多个单例类的实例

    场景二:如果 Singleton 实现了 java.io.Serializable 接口,那么这个类的实例就可能被序列化和反序列化。

    3、单例模式和静态类

    静态类也可以实现一个类只有一个对象,这又和单例模式有什么区别呢?

    1. 单例可以继承和被继承,方法可以被重写(override),但是静态方法不行。
    2. 静态方法中产生的对象会在执行后被释放,进而被GC所清理,不会一直存在于内存中。
    3. 静态类会在第一次运行时初始化(饿汉式也这样),单例模式可以有其他选择,如立即加载(饿汉式)和延迟加载(懒汉式)
    4. 基于上面两条,单例模式往往存在于DAO层,如果反复的初始化和释放会占用很多系统资源,而使用单例模式将其加载于内存中可以节省资源开销。
    5. 单例模式容易测试

    立即加载 : 在类加载初始化的时候就主动创建实例;
    延迟加载 : 等到真正使用的时候才去创建实例,不用时不去主动创建。

    静态类和单例模式情景的选择:

    情景一:不需要维持任何状态,仅仅用于全局访问,此时更适合使用静态类。

    情景二:需要维持一些特定的状态,此时更适合使用单例模式。

    4、单例模式的经典实现

    饿汉式单例(典型实现)

    想想“三个一”特点
    饿汉式单例实现的方式如下,这种方法是线程安全的,因为单例类被加载时,就会实例化一个对象并交给自己的引用,供系统使用;而且,由于这个类在整个生命周期中只会被加载一次,因此只会创建一个实例,即能够充分保证单例。

    //饿汉式单例实现
    public class Singleton1 {
        private Singleton1(){}
        private static Singleton1 singleton1 = new Singleton1();
        public static Singleton1 getInstance (){
            return singleton1;
        }
    }
    

    **缺点:**因为是立即加载的方式创建单例,所以在单例无用的情况下回造成资源的浪费,大量饿汉式单例会给系统造成极大的开销。

    饿汉式-静态代码块

    public class Singleton {
       private Singleton instance = null;
       private Singleton() {}
    	// 初始化顺序:基静态、子静态 -> 基实例代码块、基构造 -> 子实例代码块、子构造
       static {
           instance = new Singleton();
      }
    
       public static Singleton getInstance() {
           return this.instance;
      }
    }
    

    类初始化时实例化 instance

    懒汉式单例创建,五种方法

    想想“3125”中的二和五

    0)、懒汉式(典型实现)

    //不完美的饿汉式单例
    public class Singleton2 {
        private Singleton2(){}
        private static Singleton2 instance = null;
        public static Singleton2 getInstance (){
            if (instance == null){
                instance = new Singleton2();
            }
            return instance ;
        }
    }
    

    为什么说上面的饿汉式单例不完美呢,在单线程情况下,这种方法是线程安全的,但假设在多线程情况下
    多个线程会同时执行到if (instance == null),此时尚未有线程创建出instance = new Singleton2();,这时就会有多个线程进入到if判断语句中,创建出多个对象。

    这里介绍个知识点,在下面也有用到:

    当我们写了 new 操作,JVM 到底会发生什么?
    首先,我们要明白的是,new Singleton()是一个非原子操作,代码行instance = new Singleton2();的执行过程可以分为下面三步:
    (1)、memory = allocate(); //先在内存开辟空间
    (2)、ctorInstance(memory); //初始化对象
    (3)、instance = memory; //使instance 指向刚分配的内存地址(执行完这步 instance 才是非Null的)

    要留意的是:这个过程可能发生无序写入(指令重排序),也就是说上面的3行指令可能会被重排序导致先执行第3行后执行第2行,也就是说其真实执行顺序可能是下面这种:
    (1)、memory = allocate(); //先在内存开辟空间
    (2)、instance = memory; //使instance 指向刚分配的内存地址
    (3)、ctorInstance(memory); //初始化对象

    1)、同步延迟加载 — synchronized方法

    public class Singleton3 {
        private Singleton3(){}
        private static Singleton3 instance = null;
        public static synchronized Singleton3 getInstance (){
            if (instance == null){
                instance = new Singleton3();
            }
            return instance ;
        }
    }
    

    这种方法确实做到了线程安全,但是在每一个线程执行到getInstance()方法时,只有一个线程获得锁,其他线程需要等待。这样就会因为等待锁资源造成系统性能的下降。

    上面传统懒汉式单例的实现唯一的差别就在于:是否使用 synchronized 修饰 getSingleton3()方法。若使用,就保证了对临界资源的同步互斥访问,也就保证了单例。

    2)、双重检验锁模式(double checked locking pattern)

    对上面的方法进行改进

    进行两次 instance == null? 的判断,如果为true才能进入同步代码块,而在同步代码块中再检测一次是因为可能会有多个线程一起进入同步块外的 if,如果在同步块内不进行二次检验的话就有可能会生成多个实例了。

    //同步延迟加载 — synchronized块
    public class Singleton4 {
        private Singleton4(){}
        private static Singleton4 instance= null;
        public static Singleton4 getInstance(){
        	if (instance == null){
            // 使用 synchronized 块,临界资源的同步互斥访问
            synchronized (Singleton4.class){
                    if (instance == null){
                        instance = new Singleton4();
                    }
                }
            }
            return instance;
        }
    }
    

    为什么说使用synchronized块是线程不安全的呢,这里就需要用到前面提到的前置知识了。

    如果intence = new Singleton4();的执行顺序是1-2-3
    即:先分配内存空间,再初始化成员变量,最后分配引用地址。这样出来的instance 是非null的。

    但如果执行顺序是1-3-2的情况下
    即:先分配内存空间,在分配引用地址,最后再初始化变量。

    如果是后者,则在 3 执行完毕、2 未执行之前,此时另外有一个线程进行第一个判断,发现instance!=null,返回instance(但其实instance还没有完成初始化),使用会导致报错,当然发生错误的概率极低,但是这个错误我们是可以规避的。

    只需要将 instance 变量声明成 volatile 就可以了。

    双重检验锁-volatile关键字防止重排序

    public class Singleton4 {
        private Singleton4(){}
        //给instance加上了volatile关键字
        private volatile static Singleton4 instance= null;
        public static Singleton4 getInstance(){
                if (instance == null){
                // 使用 synchronized 块,临界资源的同步互斥访问
                synchronized (Singleton4.class){
                    if (instance == null){
                        instance = new Singleton4();
                    }
                }
            }
            return instance;
        }
    }
    

    使用 volatile 的主要原因是其另一个特性:禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。比如上面的例子,取操作必须在执行完 1-2-3 之后或者 1-3-2 之后,不存在执行到 1-3 然后取到值的情况。从「先行发生原则」的角度理解的话,就是对于一个 volatile 变量的写操作都先行发生于后面对这个变量的读操作(这里的“后面”是时间上的先后顺序)。

    但是特别注意
    在 Java 5 以前的版本使用了 volatile 的双检锁还是有问题的。其原因是 Java 5 以前的 JMM (Java 内存模型)是存在缺陷的,即时将变量声明成 volatile 也不能完全避免重排序,主要是 volatile 变量前后的代码仍然存在重排序问题。这个 volatile 屏蔽重排序的问题在 Java 5 中才得以修复,所以在这之后才可以放心使用 volatile。

    3)、静态内部类

    public class Singleton {  
    //静态内部类里面创建了一个Singleton单例
       private static class InstanceHolder {  
          private static final Singleton INSTANCE = new Singleton();  
      }  
       private Singleton (){}  
       public static final Singleton getInstance() {  
          return InstanceHolder.INSTANCE;  
      }  
    }  
    

    这种写法仍然使用JVM本身机制保证了线程安全问题;由于 SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖 JDK 版本。

    4)、lock机制

    // 类似双重校验锁写法
    public class Singleton {
          private static Singleton instance = null;
          private static Lock lock = new ReentrantLock();
          private Singleton() {}
          public static Singleton getInstance() {
              if(instance == null) {
                  lock.lock(); // 显式调用,手动加锁
                  if(instance == null) {
                      instance = new Singleton();
                  }
                  lock.unlock(); // 显式调用,手动解锁
              }
              return instance;
          }
    }
    

    5)、枚举法

    public enum singleton5 {
    	INSTANCE;
    	
    	private  InnerClass _instance;
    	
    	private singleton5() {
    		_instance = new InnerClass();
    	}
    	
    	public InnerClass getInstance() {
    		return _instance;
    	}
    	
    	private class InnerClass{
    		
    	}
    	
    }
    

    主要是枚举类型是值类型的数据,所以不可能获取到构造函数,也就无法通过构造函数来得到新的实例。这样可以实现很安全的单例模式。(目前很多使用枚举实现单例模式)

    缺点:
    枚举类型会造成更多的内存消耗。枚举会比使用静态变量多消耗两倍的内存,如果是Android应用,尽量避免。

    特点:
    (1)线程安全(枚举类型默认就是安全的)

    (2)避免反序列化破坏单例

    展开全文
  • java常见设计模式介绍

    2020-07-20 16:32:37
    文章目录常见设计模式介绍原型模式适用场景运用场景代理模式CGLib 和 JDK 动态代理对比Spring 中的代理选择原则静态代理和动态代理的本质区别代理模式的优缺点委派模式代理模式、委托模式、策略模式之间区别策略模式...
  •  java中单例模式是一种常见设计模式,单例模式的写法有好几种:懒汉式单例、饿汉式单例、登记式单例。这里主要介绍前两种。 单例模式有以下特点:  1、单例类只能有一个实例。  2、单例类必须自己创建自己的...
  • 工厂模式在我们日常的应用中应当算是比较广泛的一种设计模式了。今天让我们一起来学习一下,工厂的设计模式。 工厂模式在《Java与模式》中分为三类: 1)简单工厂模式(Simple Factory):不利于产生系列产品; 2...
  • 在阎宏博士的《JAVA模式》一书中开头是这样描述适配器(Adapter)模式的:  适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 ...
  • 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望...
  • 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到解耦的目的。 工厂模式可以分为三类: 简单工厂模式(Simple Factory) (可归为工厂方法模式) 工厂方法模式(Factory ...
  • 代理(Proxy)模式提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。 代理模式的主要优点有: 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用; 代理对象可以扩展目标对象的...
  • 装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。 装饰(Decorator)模式的使用场景: 需要扩展一个类的功能,或...
  • 适配器(Adapter)模式就是将一个类的接口转换成客户希望的另外一个接口。 适配器(Adapter)模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。 模式中的角色 目标接口(Target):客户所...
  • Java常见设计模式面试题

    千次阅读 2018-09-13 11:49:47
    1.请列举出在JDK中几个常用的设计模式? 单例模式(Singleton pattern)用于Runtime,Calendar和其他的一些类中。工厂模式(Factory pattern)被用于各种不可变的类如 Boolean,像Boolean.valueOf,观察者模式...
  • 在阎宏博士的《JAVA模式》一书中开头是这样描述观察者(Observer)模式的:  观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式...
  • java常见设计模式清单

    2018-03-09 09:34:50
    1. 代理模式 为其他对象提供一种代理以控制对这个对象的访问。 和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 和装饰器模式的区别:装饰器模式为了增强功能,而...

空空如也

1 2 3 4 5 ... 20
收藏数 4,592
精华内容 1,836
关键字:

java常见设计模式

java 订阅