6种创造型设计模式

工厂模式

工厂模式是为了更好管理new出来的对象, 把创建对象的任务交给工厂做, 比手动new更符合软件设计原则

简单工厂模式

包括三个角色

  • 工厂角色
  • 抽象产品角色
  • 具体产品角色

工厂角色返回的值是抽象产品角色, 但是实际上的业务逻辑都是具体产品角色, 是在工厂角色内部实例化初始化的

简单工厂把对象创建和对象使用分开了

优点:

  • 工厂类进行判断逻辑, 客户端不用创建产品对象, 实现创建使用分离
  • 客户端也不用记住产品类名称, 只用记得对应参数即可
  • 也可以引入配置文件, 做到对代码不侵入

缺点

  • 工厂类职责过重, 如果工厂类不能工作, 系统全膨蝰
  • 工厂类逻辑会随着产品增多而复杂

工厂方法模式

工厂方法模式是简单工厂的一种优化手段, 简单工程的工厂类过于复杂, 工厂方法模式不再提供统一的工厂类创建所有产品对象, 而是针对不同产品提供不同工厂。

包含4个部分

  • 抽象产品
  • 具体产品
  • 抽象工厂
  • 具体工厂

这里的抽象工厂等同于简单工厂中的工厂类,但是工厂方法模式提供具体工厂, 针对性的生产产品,将产品实例化操作延迟到子类具体工厂中,不必频繁修改抽象工厂类,解决简单工厂模式中违背开闭原则的问题

其实工厂方法模式也透露出一股多态的味道, 也叫多态工厂模式

优点:

  • 用户只用关心产品对应工厂,无需关心创建细节
  • 新增产品时候, 不用修改抽象工厂和抽象产品提供的接口,只需要增加一个具体工厂和具体产品租组,系统扩展性很高

缺点:

  • 每新增一个产品,就要增加对应的具体产品和具体工厂,当产品多了,系统中的类也将成对增加,编译运行时间也带来开销

抽象工厂模式

简单工厂模式工厂类职责过重出现了工厂方法模式,但是工厂方法模式中,一个产品类只生产一种产品,这样导致存在很多工厂类,我们考虑,将共性产品组成一个产品组,由统一工厂来生产。这就是抽象工厂模式的核心思想

包含四个角色:

  • 抽象工厂
  • 具体工厂
  • 抽象产品
  • 具体产品

此处抽象工厂模式并不只是定义生产某一产品的方法,而是定义同属于一产品族的产品

对应的具体工厂也是生产这一产品族的产品

优点:

  • 新增产品族无须改变已有系统,符合开闭原则
  • 用户只用关心产品对应工厂,无需关心创建细节,并且能够保证客户端只使用同一产品族中的对象

缺点:

  • 如果要在抽象工厂中新增某产品,需要对原有系统做较大修改,违背开闭原则,所以使用抽象工厂模式的时候,一定要对系统做好设计,否则后期修改需要耗费大量精力

单例模式

说起单例模式,不得不回想起学习synchronized的那段时光。。。

为什么出现单例,也是为了确定对象的唯一性,避免多个对象带来种种问题,例如,电脑的任务管理器,是只能打开一个的,如果说有两个任务管理器,那究竟以哪个中的数据为主?

单例模式也分为懒汉模式和饿汉模式。

懒汉模式

懒汉模式的意义在于,这个单例对象只有在不得以使用的时候才创建出来,“懒懒的”,因此叫做懒汉模式

class LazySimpleSingleton{
    private static LazySimpleSingleton lazySimpleSingleton = null;
    public static LazySimpleSingleton getInstance(){
        if(lazySimpleSingleton == null) {
            lazySimpleSingleton = new LazySimpleSingleton();
        }
        return lazySimpleSingleton;
    }
}

懒汉模式一般还可以优化,结合synchroinzed成双重校验锁定,避免高并发时候出现线程安全问题

饿汉模式

饿汉模式的意义在于,这个单例对象不管我想不想用都早早创建出来了,“像没吃过饭一样着急”,因此叫饿汉模式

class Singleton{
    private static final Singleton singleton = new Singleton();
    private Singleton(){

    }
    public static Singleton getInstance() {
        return singleton;
    }
}

饿汉模式不能延迟加载,不使用就会白白占用内存,懒汉模式又存在线程安全问题,性能可能受影响,是否还有更好的方式创建单例对象呢?

静态内部类

/**
 * 内部类是在使用的时候才会调用
 */
class LazyStaticInnerClassSingleton{
    private LazyStaticInnerClassSingleton lazyStaticInnerClassSingleton(){}

    private static LazyStaticInnerClassSingleton getInstance(){
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder{
        private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
    }
}

内部类在使用时候才会调用,因此具备延迟加载;调用getInstance的时候,JVM加载这个内部类会保证线程安全性。

原型模式

原型模式也是克隆模式,核心在于克隆已有对象。

如果我们手写一个克隆方法,就要考虑手动将对象的各种属性进行拷贝,Java底层给我们提供了方法可以简化我们

的体力劳动,所有对象都有一个共同父类就是Object类,这个类中就有clone可以作为浅克隆,注意在使用clone方法的时候,该对象一定要继承Cloneable接口,否则调用clone的时候会报错CloneNotSupportedException。

单纯调用clone方法只是浅克隆,遇到包含引用类型对象的时候,克隆对象中的引用类型会和原对象的引用类型公用同一个空间。Java中要想实现深克隆,我们可以通过序列化的方式,将对象写入流,对这个流对象进行拷贝,然后再反序列化回来,即可实现深克隆。实现深克隆的条件就是该类必须实现Serializable接口。

优点:

  • 创建对象实例复杂时,可以使用原型模式简化创建过程,复制一个已有的实例对象提高效率
  • 使用深克隆拷贝对象,保持对象状态,在将来某一个时刻还能反悔到原来的状态

缺点:

  • 每一个类都配备一个克隆方法,如果以后需要修改克隆逻辑,违反开闭原则

建造者模式

我在有了Spring的一些基础上理解建造者,它的意思是不是等同于依赖注入?在注入的时候考虑注入顺序以及注入的逻辑即可

建造者包含4个角色:

  • 抽象建造者
  • 具体建造者
  • 产品角色
  • 指导者

抽象建造者中抽象了众多创建产品角色的各个部分的方法,具体建造者对其进行具体实现,并可以使用getResult等方法返回创建的产品。

指导者主要是为了隔离客户和创建过程,并控制产品创建的过程(创建产品各部分的顺序等)

class Product  {

       private  String partA; //定义部件,部件可以是任意类型,包括值类型和引用类型

       private  String partB;

       private  String partC;

       //partA的Getter方法和Setter方法省略

       //partB的Getter方法和Setter方法省略

       //partC的Getter方法和Setter方法省略

}

abstract class Builder {

     //创建产品对象

       protected  Product product=new Product();

      

       public  abstract void buildPartA();

       public  abstract void buildPartB();

       public  abstract void buildPartC();

      

     //返回产品对象

       public  Product getResult() {

              return  product;

       }

}

class Director {

       private  Builder builder;

      

       public  Director(Builder builder) {

              this.builder=builder;

       }

      

       public  void setBuilder(Builder builder) {

              this.builder=builer;

       }

      

     //产品构建与组装方法

       public Product construct() {

              builder.buildPartA();

              builder.buildPartB();

              builder.buildPartC();

              return builder.getResult();

       }

}

对于客户端来说,只需要关系建造者就可以了,不需要关心产品对象的具体组装过程,只需要指定具体的建造者类型就行

Builder  builder = new ConcreteBuilder(); //指定具体建造者类型

Director director = new  Director(builder);

Product product = director.construct();

PS

感觉只有单例原型模式最熟悉了,尤其是后面的结构型模式看的头痛,不和源码结合一下很难理解。。。之后可能还得重新总结一版

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值