经常使用的设计模式

1、单例模式:html

  • 一、单例类只能有一个实例。
  • 二、单例类必须本身建立本身的惟一实例。
  • 三、单例类必须给全部其余对象提供这一实例。

优势:java

  • 一、在内存里只有一个实例,减小了内存的开销,尤为是频繁的建立和销毁实例(好比管理学院首页页面缓存)。
  • 二、避免对资源的多重占用(好比写文件操做)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。数据库

使用场景:编程

  • 一、要求生产惟一序列号。
  • 二、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 三、建立的一个对象须要消耗的资源过多,好比 I/O 与数据库的链接等。

注意事项:getInstance() 方法中须要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入形成 instance 被屡次实例化。设计模式

单例模式的几种实现方式

1.饿汉式(线程安全,调用效率高,可是,不能延时加载)缓存

// 饿汉式单例
public class Singleton1 {
 
    // 指向本身实例的私有静态引用,主动建立
    private static Singleton1 singleton1 = new Singleton1();
 
    // 私有的构造方法
    private Singleton1(){}
 
    // 以本身实例为返回值的静态的公有方法,静态工厂方法
    public static Singleton1 getSingleton1(){
        return singleton1;
    }
}

咱们知道,类加载的方式是按需加载,且加载一次。。所以,在上述单例类被加载时,就会实例化一个对象并交给本身的引用,供系统使用;并且,因为这个类在整个生命周期中只会被加载一次,所以只会建立一个实例,即可以充分保证单例。安全

优势:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。多线程

缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。若是从始至终从未使用过这个实例,则会形成内存的浪费。并发

2.懒汉式(线程安全,调用效率低,可是,能够延时加载)框架

// 懒汉式单例
public class Singleton2 {
 
    // 指向本身实例的私有静态引用
    private static Singleton2 singleton2;
 
    // 私有的构造方法
    private Singleton2(){}
 
    // 以本身实例为返回值的静态的公有方法,静态工厂方法
    public static Singleton2 getSingleton2(){
        // 被动建立,在真正须要使用时才去建立
        if (singleton2 == null) {
            singleton2 = new Singleton2();
        }
        return singleton2;
    }
}

咱们从懒汉式单例能够看到,单例实例被延迟加载,即只有在真正使用的时候才会实例化一个对象并交给本身的引用。

这种写法起到了Lazy Loading的效果,可是只能在单线程下使用。若是在多线程下,一个线程进入了if (singleton == null)判断语句块,还将来得及往下执行,另外一个线程也经过了这个判断语句,这时便会产生多个实例。因此在多线程环境下不可以使用这种方式。

3.双重检测锁式(因为JVM底层内部模型缘由,偶尔会出现问题。不建议使用)

public class Singleton
    {
        private static Singleton instance;
        //程序运行时建立一个静态只读的进程辅助对象
        private static readonly object syncRoot = new object();
        private Singleton() { }
        public static Singleton GetInstance()
        {
            //先判断是否存在,不存在再加锁处理
            if (instance == null)
            {
                //在同一个时刻加了锁的那部分程序只有一个线程能够进入
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

Double-Check概念对于多线程开发者来讲不会陌生,如代码中所示,咱们进行了两次if (singleton == null)检查,这样就能够保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。

使用双重检测同步延迟加载去建立单例的作法是一个很是优秀的作法,其不但保证了单例,并且切实提升了程序运行效率

优势:线程安全;延迟加载;效率较高。

4.静态内部类式(线程安全,调用效率高,能够延时加载)

public sealed class Singleton{
    private static class SingletonInstance{
        //在第一次引用类的任何成员时建立实例,公共语言运行库负责处理变量初始化
        private static final Singleton instance=new Singleton();
        }
        private Singleton() { }
        public static Singleton getInstance(){
            return SingletonInstance.instance;
        }
    }

外部类没有static属性,则不会像饿汉式那样当即加载对象。

只有真正调用getInstance(),才会加载静态内部类。加载类时是线程安全的。instance是static final类型,保证了内存中只有这样一个实例存在,并且只能被赋值一次,从而保证了线程安全性。

兼备了并发高效调用和延迟加载的优点!

5.枚举实现单例模式

public enum Singleton{
   //定义一个枚举元素,它就表明了Singleton的一个实例
    INSTANCE;
     //单例能够有本身的操做
     public void singletonOperation(){
          //功能处理(可额外添加须要的操做)   
     }             
}

优势:实现简单

   枚举自己就是单例模式。因为JVM根本上提供保障,避免经过反射和反序列化的漏洞

缺点:无延迟加载

 

2、工厂模式

实现了建立者和调用者的分离。

分类:简单工厂模式、工厂方法模式、抽象工厂模式

 

面向对象设计的基本原则

OCP(开闭原则):一个软件的实体应当对扩展开放,对修改关闭。

DIP(依赖倒转原则):要针对接口编程,不要针对实现编程。

LOD(迪米特法则):只与你直接的朋友通讯,而避免和陌生人通讯。

 

工厂核心本质:

实例化对象,用工厂方法代替new操做,将选择实现类、建立对象统一管理和控制,从而将调用者跟咱们的实现类解耦。

 

简单工厂模式

简单工厂模式是属于建立型模式,又叫作静态工厂方法模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定建立出哪种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,能够理解为是不一样工厂模式的一个特殊实现。

咱们将建立一个 Shape 接口

 public interface Shape { void draw(); } 

实现 Shape 接口的实体类

Rectangle.java

public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

Square.java

public class Square implements Shape {
 
    @Override
    public void draw() {
      System.out.println("Inside Square::draw() method.");
  
 }

Circle.java

public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
  
   }

}

 

建立一个工厂,生成基于给定信息的实体类的对象。

public class ShapeFactory {
    
   //使用 getShape 方法获取形状类型的对象
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

 

使用该工厂,经过传递类型信息来获取实体类的对象。

public class FactoryPatternDemo {
 
   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();
 
      //获取 Circle 的对象,并调用它的 draw 方法
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //调用 Circle 的 draw 方法
      shape1.draw();
 
      //获取 Rectangle 的对象,并调用它的 draw 方法
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //调用 Rectangle 的 draw 方法
      shape2.draw();
 
      //获取 Square 的对象,并调用它的 draw 方法
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //调用 Square 的 draw 方法
      shape3.draw();
   }
}

执行程序,输出结果:

Inside Circle::draw() method. Inside Rectangle::draw() method. Inside Square::draw() method.



2、工厂方法模式
工厂方法模式Factory Method,又称多态性工厂模式。在工厂方法模式中,核心的工厂类再也不负责全部的产品的建立,而是将具体建立的工做交给子类去作。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪个产品类应当被实例化这种细节。
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先彻底实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,能够应用于产品结果复杂的场合。
 
建立抽象工厂:
   public interface IFactory
    {

        ICar CreateCar();
   
 }

 

建立抽象产品

 public interface ICar
    {
   
     void GetCar();
   
 }

 

 建立具体工厂代码:

  //  具体工厂类: 用于建立跑车类
    public class SportFactory : IFactory
    {
        public ICar CreateCar()
        {
            return new SportCar();
        }
    }

    //  具体工厂类: 用于建立越野车类
    public class JeepFactory : IFactory
    {
        public ICar CreateCar()
        {
            return new JeepCar();
        }
    }

    //  具体工厂类: 用于建立两厢车类
    public class HatchbackFactory : IFactory
    {
        public ICar CreateCar()
        {
            return new HatchbackCar();
        }
    }

 

 建立具体产品代码:

    // 具体产品类: 跑车
    public class SportCar : ICar
    {
        public void GetCar()
        {
            System.out.println("跑车");
        }
    }

    // 具体产品类: 越野车
    public class JeepCar : ICar
    {
        public void GetCar()
        {
            System.out.println("越野车");
        }
    }

    // 具体产品类: 两箱车
    public class HatchbackCar : ICar
    {
        public void GetCar()
        {
            System.out.println("两箱车");
        }
    }

 

建立客户端代码:

class Client{
        public static void main(string[] args){
           ICar c1 = new SportFactory.CreateCar();
       ICar c2 = new JeepFactory .CreateCar();
       ICar c3 = new HatchbackFactory .CreateCar();
      
        c1.GetCar();
        c2.GetCar();
        c3.GetCar();
        }
    }

工厂方法的优势/缺点: 

  • 优势:
    • 子类提供挂钩。基类为工厂方法提供缺省实现,子类能够重写新的实现,也能够继承父类的实现。-- 加一层间接性,增长了灵活性
    • 屏蔽产品类。产品类的实现如何变化,调用者都不须要关心,只需关心产品的接口,只要接口保持不变,系统中的上层模块就不会发生变化。
    • 典型的解耦框架。高层模块只须要知道产品的抽象类,其余的实现类都不须要关心,符合迪米特法则,符合依赖倒置原则,符合里氏替换原则。
    • 多态性:客户代码能够作到与特定应用无关,适用于任何实体类。
  • 缺点:须要Creator和相应的子类做为factory method的载体,若是应用模型确实须要creator和子类存在,则很好;不然的话,须要增长一个类层次。(不过说这个缺点好像有点吹毛求疵了)

 代理模式:

 http://www.javashuo.com/article/p-vbeoztly-dd.html

相关文章
相关标签/搜索