java设计模式总结(二) ---- 五种创建型模式(引用一下韩老师的代码)

设计模式的分类

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

 https://www.cnblogs.com/fswhq/p/sjms.html 这是我看见的一位大佬的文章可以,看一下

创建模式(5种)

工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式

 

1,单例设计模式

定义:确保一个类最多只有一个实例,并提供一个全局访问点

八种方式:

1> 饿汉式(静态常量)

2> 饿汉式(静态代码块)

3> 懒汉式(线程不安全)

4> 懒汉式(同步方法)

5> 懒汉式(同步代码块)

6> 双重检查

7> 静态内部类

8> 枚举

1.1饿汉式(静态常量)

class Singleton {
    
    //1. 构造器私有化, 外部能new
    private Singleton() {
        
    }
    
    //2.本类内部创建对象实例
    private final static Singleton instance = new Singleton();
    
    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }
    
}

优点:简单,没有线程安全问题

缺点:老友Lazy Loading效果,没有使用该单例时,浪费内存

1.2饿汉式(静态代码块)

class Singleton {
    
    //1. 构造器私有化, 外部能new
    private Singleton() {
        
    }
    

    //2.本类内部创建对象实例
    private  static Singleton instance;
    
    static { // 在静态代码块中,创建单例对象
        instance = new Singleton();
    }
    
    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }
    
}

优缺点和上面一种饿汉式差不多

1.3懒汉式(线程不安全)

class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一个静态的公有方法,当使用到该方法时,才去创建 instance
    //即懒汉式
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

优缺点:

有Lazy Loading的效果,只能在单线程下使用

多线程下会出现多个实例

不要使用这种方式

class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

优缺点:没有线程安全问题

效率太低,每次都要进去都要同步

1.5懒汉式(线程安全,同步代码块)

// 懒汉式(线程安全,同步方法)
class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static  Singleton getInstance() {
        if(instance == null) {
            synchronized(Singleton.class){

                instance = new Singleton();
            }
        }
        return instance;
    }
}

 

多线程时会产生多例

1.6 双重检查

class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
    //同时保证了效率, 推荐使用
    
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }
            
        }
        return instance;
    }
}

优缺点:线程安全;延迟加载;效率高

1.7 静态内部类

// 静态内部类完成, 推荐使用
class Singleton {
    private static volatile Singleton instance;
    
    //构造器私有化
    private Singleton() {}
    
    //写一个静态内部类,该类中有一个静态属性 Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton(); 
    }
    
    //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
    
    public static synchronized Singleton getInstance() {
        
        return SingletonInstance.INSTANCE;
    }
}

优缺点:使用类加载机制;使用时在实例化;第一次加载时才初始化jvm保证单例

1.8 枚举

//使用枚举,可以实现单例, 推荐
enum Singleton {
    INSTANCE; //属性
}

JDK5.0新特性,还防止了序列化

1.9单例模式在JDK中的使用

使用的饿汉式

 

 

 

 

 1.10细节说明和使用事项

 

 

 

                         

1 工厂模式(包括简单工厂,工厂方法,抽象工厂)

 

1.1 简单工厂模式

 

定义:定义了一个创建对象的类,由这个类来封装实例化对象的行为。

 

举例:(我们举一个pizza工厂的例子)

使用简单工厂:

public Pizza createPizza(String orderType) {

        Pizza pizza = null;

        System.out.println("使用简单工厂模式");
        if (orderType.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName(" 希腊披萨 ");
        } else if (orderType.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName(" 奶酪披萨 ");
        } else if (orderType.equals("pepper")) {
            pizza = new PepperPizza();
            pizza.setName("胡椒披萨");
        }
        
        return pizza;
    }

1.2 工厂方法模式

定义:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。

举例:(我们依然举pizza工厂的例子,不过这个例子中,pizza产地有两个:伦敦和纽约)。添加了一个新的产地,如果用简单工厂模式的的话,我们要去修改工厂代码,并且会增加一堆的if else语句。而工厂方法模式克服了简单工厂要修改代码的缺点,它会直接创建两个工厂,纽约工厂和伦敦工厂。类图如下:

 

 

 

 在简单工厂的基础上增加了多个工厂,就让一个父类工厂去管理

子类的主要代码和简答工厂差不多

public class BJOrderPizza extends OrderPizza {

    
    @Override
    Pizza createPizza(String orderType) {
    
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}

1.3 抽象工厂模式

 定义:定义了一个接口用于创建相关或有依赖关系的对象族,而无需明确指定具体类。

举例:(我们依然举pizza工厂的例子,pizza工厂有两个:纽约工厂和伦敦工厂)。类图如下:

 

 

 

//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
    //让下面的工厂子类来 具体实现
    public Pizza createPizza(String orderType);
}

把工厂方法模式加到接口之中,区别感觉不大

1.4工厂在JDK中的使用

  在Calader中使用了简单工厂模式,根据时区来创建相应的子类对象

总结:工厂的好处,在创建的对象的时候我们会有各种各样的要求,我们把这一部分都讲给工厂去处理。我们在使用的时候只需要用方法区获取到类就行。不代码分离开

    简单工厂:根据条件new

    工厂方法:用父类来管理相似的工厂类

    抽象工厂模式:用接口来管理相关的工厂类

ps:该模式是违反ocp原则的,对于新类工厂无法进行扩展。因为要去改工厂原本的方法

3原型模式

原型模式就是对一个类进行复制,在Cloneable接口中已经实现了,我们重写一下就行

@Override
    protected Object clone()  {
        
        Sheep sheep = null;
        try {
            sheep = (Sheep)super.clone();
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println(e.getMessage());
        }
        // TODO Auto-generated method stub
        return sheep;
    }

深拷贝和浅拷贝:如果我们在clone方法中,拷贝对于类中以其他类作为属性时,我们把他指向同一个对象,这样复制出来的过程叫浅拷贝,否则,就是深拷贝。如下图

浅拷贝:

我们的类属性:

重写clone:

客户端复制:

运行结果:

 

上图就是浅拷贝。

 

下面是深拷贝,有两种方式,方式一在复制属性对象时我们把该对象里面的clone也重新并且调用:

public String name; //String 属性
    public DeepCloneableTarget deepCloneableTarget;// 引用类型
    public DeepProtoType() {
        super();
    }
    
    
    //深拷贝 - 方式 1 使用clone 方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        
        Object deep = null;
        //这里完成对基本数据类型(属性)和String的克隆
        deep = super.clone(); 
        //对引用类型的属性,进行单独处理
        DeepProtoType deepProtoType = (DeepProtoType)deep;
        deepProtoType.deepCloneableTarget  = (DeepCloneableTarget)deepCloneableTarget.clone();
        
        // TODO Auto-generated method stub
        return deepProtoType;
    }

方式二,进行序列化,再进行反序列化:

public String name; //String 属性
    public DeepCloneableTarget deepCloneableTarget;// 引用类型
    public DeepProtoType() {
        super();
    }
public Object deepClone() {
        
        //创建流对象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        
        try {
            
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //当前这个对象以对象流的方式输出
            
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepProtoType copyObj = (DeepProtoType)ois.readObject();
            
            return copyObj;
            
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                // TODO: handle exception
                System.out.println(e2.getMessage());
            }
        }
        
    }

原型设计模式在Spring bean设置当中使用了

 

 

以上就是原型模式的全部内容。

4 建造者模式(生成器模式)

作用:把一个复杂的对象,内部结构和操作分离开来。内部结构不呈现给用户

以造房子为例,传统方式

 

画红线处,操作在用户用体现。

 

 

 

 

使用建造者模式:

 

 指挥者去完成功能

 

 

 

 

 在JDK--StringBuilder中的应用

好了,五中创建型模式就写到这儿,我写的东西不会放全部代码,会多给原理图和重要代码截图

 

posted @ 2020-10-25 18:11  L三木1121  阅读(173)  评论(0编辑  收藏  举报