【设计模式】创建型模式(单例模式,原型模式,简单工厂模式,工厂方法模式,抽象工厂模式,建造者模式)

单例模式

定义的类只有一个实例,不可以通过new关键字来获取对象,只可以通过公共的某个方法获取对象

应用举例

  • 操作系统的文件系统
  • 线程池
  • 数据库连接池
  • web应用的配置对象
  • 缓存
  • spring

在spring中 , 大部分的bean都需要将尝使用,重复的创建会造成内存的浪费 , 也消耗性能 , 所以spring的bean可以使用单例去减少GC

单例模式的特点

  • 单例类只有一个实例对象;

  • 该单例对象必须由单例类自行创建;

  • 单例类对外提供一个访问该单例的全局访问点。

单例模式的优点和缺点

单例模式的优点:

  • 单例模式可以保证内存里只有一个实例,减少了内存的开销。
  • 可以避免对资源的多重占用。
  • 单例模式设置全局访问点,可以优化和共享资源的访问。

单例模式的缺点:

  • 单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。
  • 在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
  • 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。

java实现单例模式

懒汉式单例

类加载时生成单例 , 不调用不生成

配合双重检测的锁 , 更好的防止反射 , 或者多并发的对单例影响

package com.cxy.Gof.singleton;
/**
 * @ClassName LazySingleton
 * @Author 陈新予(blank)
 * @Date 2021/6/1
 * @Version 1.0
 */
public class LazySingleton {
    private static volatile LazySingleton instance;
    private static volatile boolean lock = true;
    private LazySingleton(){
        synchronized (LazySingleton.class){
            if(!lock){
                throw new RuntimeException("别反射了鸽!");
            }
            if(instance!=null){
                throw new RuntimeException("别反射了鸽!");
            }else{
                System.out.println("创建类......创建成功!");
            }
        }
    }
    public synchronized static LazySingleton getInstance(){
        if(instance==null){
            instance = new LazySingleton();
            lock = false;
        }
        return instance;
    }
}

饿汉式单例

调用前 , 单例就已经存在了

package com.cxy.Gof.singleton;
/**
 * @ClassName HungrySingleton
 * @Author 陈新予(blank)
 * @Date 2021/6/1
 * @Version 1.0
 */
public class HungrySingleton {
    private static volatile HungrySingleton instance = new HungrySingleton();
    private HungrySingleton(){
        System.out.println("创建类......创建成功!");
    }
    public synchronized static HungrySingleton getInstance(){
        return instance;
    }
}

测试

在这里插入图片描述

原型模式

通过原来的对象 , 快速的生成一个新的对象 , 复制期间 , 类的实现细节不会暴露

原型模式的优缺点

原型模式的优点:

  • Java自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
  • 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

原型模式的缺点:

  • 需要为每一个类都配置一个 clone 方法
  • clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
  • 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。

java实现原型模式

package com.cxy.Gof.prototype;
/**
 * @ClassName Student
 * @Author 陈新予(blank)
 * @Date 2021/6/1
 * @Version 1.0
 */
public class Student implements Cloneable{
    public String name;
    public Student(){
        System.out.println("创建中......创建成功!");
    }
    public Student setName(String name){
        this.name = name;
        return this;
    }
    public Student clone() throws CloneNotSupportedException {
        return (Student)super.clone();
    }
}

测试

在这里插入图片描述

两个对象不相同 , 但无参构造只调用了一次

工厂模式

把对象的创建交给工厂 , 抽象出工厂接口 , 多用于生成复杂对象

简单工厂模式优缺点

优点:

  • 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。

  • 客户端无需知道所创建具体产品的类名,只需知道参数即可。

  • 也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。

缺点:

  • 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。

  • 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度

  • 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂

  • 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。

工厂方法模式

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
  • 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
  • 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。

缺点:

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度
  • 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。

抽象方法模式

优点:

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
  • 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
  • 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。

缺点:

  • 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。

java实现工厂模式

简单工厂模式

/*****************************工厂接口*****************************/
public interface Product {
    void show();
}
/*****************************产品1*****************************/
public class ProductImpl1 implements Product{
    @Override
    public void show() {
        System.out.println("产品一号......");
    }
}
/*****************************产品2*****************************/
public class ProductImpl2 implements Product{
    @Override
    public void show() {
        System.out.println("产品二号......");
    }
}
/*****************************测试类*****************************/
public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        boolean li = true;
        while (li){
            System.out.println("请输入你要建立的对象:1 2 3");
            int case1 = sc.nextInt();
            switch (case1){
                case 1:
                    System.out.println(new ProductImpl1());
                    break;
                case 2:
                    System.out.println(new ProductImpl1());
                    break;
                case 3:
                    System.out.println("退出了哦~");
                    li = false;
                    break;
            }
        }
    }
}

在这里插入图片描述

工厂方法模式

/*****************************工厂接口*****************************/
public interface Prodect {
    void show();
}
/*****************************新增工厂接口*****************************/
public interface AbstructFactory {
    Prodect newProdect();
}
/*****************************产品1*****************************/
public class Con1 implements Prodect{
    @Override
    public void show() {
        System.out.println("产品1........");
    }
}
/*****************************产品2*****************************/
public class Con2 implements Prodect {
    @Override
    public void show() {
        System.out.println("产品2........");
    }
}
/*****************************工厂1*****************************/
public class ConFactory1 implements AbstructFactory{
    @Override
    public Prodect newProdect() {
        System.out.println("这里是工厂1-->生成产品1:");
        return new Con1();
    }
}
/*****************************工厂2*****************************/
public class ConFactory2 implements AbstructFactory{
    @Override
    public Prodect newProdect() {
        System.out.println("这里是工厂2-->生成产品2:");
        return new Con2();
    }
}
/*****************************测试类*****************************/
public class Test {
    public static void main(String[] args) {
        ConFactory1 factory1 = new ConFactory1();
        ConFactory2 factory2 = new ConFactory2();
        factory1.newProdect().show();
        factory2.newProdect().show();
    }
}

在这里插入图片描述

抽象工厂模式


建造者模式

将一个复杂对象的构造和他的表示分离 , 使得同样的构建过程可以创建不同的表示形式 , 被称为建造者模式

优缺点

优点:

  • 封装性好 , 构建和表示分离
  • 拓展性好 , 有利于系统的解耦
  • 客户端不必知道细节 , 由建造者不断地细化

缺点:

  • 产品的组成部分必须要相同
  • 产品一旦修改 , 则建造者也需要修改

java实现建造者模式

/*****************************产品类*****************************/
public class Prodect {
    private String name;
    private int age;
    private String sex;
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public void show(){
        System.out.println("我是:"+name+",今年"+age+"岁了,是个"+sex+"人");
    }
}
/*****************************建造者抽象类*****************************/
public abstract class Builder {
    protected Prodect prodect = new Prodect();
    public abstract void buildName(String name);
    public abstract void buildAge(int age);
    public abstract void buildSex(String sex);
    public Prodect getProdect(){
        return prodect;
    }
}
/*****************************建造者实现类*****************************/
public class BuilderImpl extends Builder {
    @Override
    public void buildName(String name) {
        prodect.setName(name);
    }
    @Override
    public void buildAge(int age) {
        prodect.setAge(age);
    }
    @Override
    public void buildSex(String sex) {
        prodect.setSex(sex);
    }
}
/*****************************实施者*****************************/
public class Director {
    private Builder builder;
    public Director(Builder builder){
        this.builder = builder;
    }
    public Prodect build(String name,int age,String sex){
        builder.buildName(name);
        builder.buildAge(age);
        builder.buildSex(sex);
        return builder.getProdect();
    }
}
/*****************************客户*****************************/
public class Client {
    public static void main(String[] args) {
        Director director = new Director(new BuilderImpl());
        Prodect prodect = director.build("李华", 18, "男");
        prodect.show();
    }
}

在这里插入图片描述

应用

链式编程

set方法返回this

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值