23种设计模式之创建型模型

先写创建型模式,后续会写结构型模式和行为型模式,分开写主要怕没保存草稿或者误操作.

前言:

1) 设计模式,不是一种语言,也不是什么新api,更不是什么新的语法.

2) 设计模式,是前辈们,不断总结,不断打磨出的设计方法.不同设计模式适用于不同的场景.

3) 设计模式,公认有23种,分别对应23种设计场景.这些设计模式,我们不用怀疑他的功能!

因为这些设计模式是经过长期实践考验而留存下来的.

4) 千万不要以为有任何一种设计模式,他能解决任何问题,每一种设计模式只能用于适合的场景,而不

是万能的.

5) 设计模式有优点,也有缺点.我们不要为了使用设计模式而使用设计模式.切记防止"模式滥用".

6) 23种设计模式,背后其实是7大设计原则.也就是说,每种设计模式都归属于一个或者多个设计原则.

在了解设计模式之前,我们首先要了解七大设计原则,这里不做过多叙述.理解即可.

设计模式推演过程不做展示,只保存完整设计模式代码,供后续场景参考,全是干货.

设计模式分类:

/*设计模式业界公认的有23种分为三种类型
1.创建型模式:单例模式,抽象工厂模式,原型模式,建造者模式,工厂模式
2.结构型模式:适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式
3.行为型模式:模板方法模式,命令模式,访问者模式,迭代器模式,观察者模式,中介者模式,备忘录模式,
        解释器模式(intepreter模式),状态模式,策略模式,职责链模式(责任链模式)
*/

七大设计原则:

/*七大设计原则
1.单一职责:每个方法,每个类,每个框架都只做一个事
2.开闭原则:对扩展开放,对修改关闭
3.接口隔离原则:一个接口只有一套增删改查,如果有多种类型的,请写多个接口
4.依赖倒置原则:上层不依赖于下层,他们都应该依赖于抽象,上层值调用方,下层指被调用方
5.迪米特法则(最少知道原则):一个类对于其他类知道的越少越好.只和朋友通信.朋友指:
    类中字段,方法的参数,方法的返回值,方法中实例化出来的对象.
6.里氏替换原则:任何能使用父类对象的地方,都能透明的替换成其子类
7.组合/聚合复用原则(组合优于继承原则):尽量使用组合/聚合,尽量不使用类的继承
 */

下面先介绍创建型模式

单例模式:


/*单例模式:在一定的方法中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法).
        比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session
        对象.SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个
        SessionFactory就够,这时就会使用到单例模式.
单例模式有8种分别为:
1)饿汉式(静态常量)
2)饿汉式(静态代码块)
3)懒汉式(线程不安全)
4)懒汉式(线程安全,同步方法)
5)懒汉式(线程安全,同步代码块)
6)双检索模式(双重检查模式)
7)静态内部类
8)枚举
 */

/*单例模式使用场景:
        1) 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需
        要频繁创建销毁的对象,使用单例模式可以提高系统性能
        2) 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使
        用new
        3) 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或
        耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数
        据库或文件的对象(比如数据源、session工厂等)*/



1.饿汉式-静态常量(不推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;


//饿汉式(静态常量)
public class SingleTon01 {
    //私有化构造器,防止直接new对象
    private SingleTon01() {
    }
    //创建一个静态的对象实例
    private static SingleTon01 instance = new SingleTon01();
    //提供一个public静态方法,可以返回实例
    public static SingleTon01 getInstance(){
        return instance;
    }

/*    优缺点说明:
            1) 优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同
    步问题。
            2) 缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始
    至终从未使用过这个实例,则会造成内存的浪费
            3) 这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载
    时就实例化,在单例模式中大多数都是调用getInstance方法, 但是导致类装载
    的原因有很多种,因此不能确定有其他的方式(或者其他的静态方法)导致类
    装载,这时候初始化instance就没有达到lazy loading的效果
            4) 结论:这种单例模式可用,可能造成内存浪费*/

    public static void main(String[] args) {
        SingleTon01 instance = getInstance();
        SingleTon01 instance1 = getInstance();
        //判断内存地址是否相等
        System.out.println(instance == instance1);
        //判断哈希code是否相等
        System.out.println(instance.hashCode());
        System.out.print(instance1.hashCode());

        //源码分析:在jdk中runtime就是单例模式(经典的饿汉式)
        Runtime runtime = Runtime.getRuntime();
    }
}

2.饿汉式-静态代码块(不推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;

//饿汉式(静态代码块)
public class SingleTon02 {
    private static SingleTon02 instance;
    //在静态代码块执行时,创建单例对象
    static {
        instance = new SingleTon02();
    }
    private SingleTon02(){}
    public static SingleTon02 getInstance(){
        return instance;
    }
//    优缺点说明:
//            1) 这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块
//    中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优
//    缺点和上面是一样的。
//            2) 结论:这种单例模式可用,但是可能造成内存浪费
}

3.懒汉式-线程不安全(不推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;

//懒汉式(线程不安全)
public class SingleTon03 {
    private static SingleTon03 singleTon;
    private SingleTon03(){}
    //当调用getInstance 才创建单例对象,懒汉式
    public static SingleTon03 getInstance(){
        if (singleTon == null){
            singleTon = new SingleTon03();
        }
        return singleTon;
    }
/*    优缺点说明:
            1) 起到了Lazy Loading的效果,但是只能在单线程下使用。
            2) 如果在多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及
    往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以
            在多线程环境下不可使用这种方式
            3) 结论:在实际开发中,不要使用这种方式.*/
}

4.懒汉式-线程安全(不推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;

//懒汉式(线程安全,同步方法)
public class SingleTon04 {
    private static SingleTon04 singleTon04;
    private SingleTon04(){

    }
    //加入了同步代码,解决线程不安全问题
    public static synchronized SingleTon04 getInstance(){
        if (singleTon04 == null){
            singleTon04 = new SingleTon04();
        }
        return singleTon04;
    }

/*    优缺点说明:
            1) 解决了线程不安全问题
            2) 效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行
    同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,
    直接return就行了。方法进行同步效率太低
            3) 结论:在实际开发中,不推荐使用这种方式*/
}

5.懒汉式-线程安全(不推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;

//懒汉式(线程安全,同步代码块)
public class SingleTon05 {
    private static SingleTon05 singleTon05;
    private SingleTon05() {
    }

    public static SingleTon05 getInstance(){
        if (singleTon05 == null){
            synchronized (SingleTon05.class){
                singleTon05 = new SingleTon05();
            }
        }
        return singleTon05;
    }

/*    优缺点说明:
            1) 这种方式,本意是想对第四种实现方式的改进,因为前面同步方法效率太低,
    改为同步产生实例化的的代码块
            2) 但是这种同步并不能起到线程同步的作用。跟第3种实现方式遇到的情形一
    致,假如一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,
    另一个线程也通过了这个判断语句,这时便会产生多个实例
            3) 结论:在实际开发中,不能使用这种方式*/
}

6.双检锁式(推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;

//双检锁模式(双重检查模式)
public class SingleTon06 {
    private static volatile SingleTon06 singleTon06;
    private SingleTon06() {
    }
    public static SingleTon06 getInstance(){
        if (singleTon06 == null){
            synchronized (SingleTon06.class){
                if (singleTon06 == null){
                    singleTon06 = new SingleTon06();
                }
            }
        }
        return singleTon06;
    }

/*    优缺点说明:
            1) Double-Check概念是多线程开发中常使用到的,如代码中所示,我们进行了两
    次if (singleton == null)检查,这样就可以保证线程安全了。
            2) 这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),
    直接return实例化对象,也避免的反复进行方法同步.
            3) 线程安全;延迟加载;效率较高
            4) 结论:在实际开发中,推荐使用这种单例设计模式*/
}

7.静态内部类(推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;

//静态内部类
public class SingleTon07 {
    private SingleTon07() {
    }
    //在SingleTon07类装载的时候SingletonInstance静态内部类不会装载,类装载的时候没有线程安全问题
    private static class SingletonInstance{
        private static final SingleTon07 INSTANCE = new SingleTon07();
    }
    public static SingleTon07 getInstance(){
        return SingletonInstance.INSTANCE;
    }

/*    优缺点说明:
            1) 这种方式采用了类装载的机制来保证初始化实例时只有一个线程。
            2) 静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化
    时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的
    实例化。
            3) 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们
    保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
            4) 优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
            5) 结论:推荐使用.*/
}

8.枚举(推举)

package com.hjm.shd.shardingspheredemo.designPatterns.design1;
//枚举
public class SingleTon08 {
    public static void main(String[] args) {
        Singleton instance = Singleton.INSTANCE;
        Singleton instance1 = Singleton.INSTANCE;
        System.out.println(instance == instance1);
        instance.sayOK();


    }
    enum Singleton{
        INSTANCE;
        public void sayOK(){
            System.out.println("ok");
        }
    }

/*    优缺点说明:
            1) 这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而
    且还能防止反序列化重新创建新的对象。
            2) 这种方式是Effective Java作者Josh Bloch 提倡的方式
            3) 结论:推荐使用*/
}

工厂模式:

1.简单工厂模式:

简单工厂模式又叫静态工厂模式,是由一个工厂对象决定创建出那种产品类的实例.

简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为

使用场景:在软件开发中,当我们会用到大量创建某种、某类或者某批对象时,就会用到工厂模式.

简单工厂模式适用于具体产品不多,且产品不经常变化的场景,如果具体产品很多,会导致产品工厂臃肿,耦合度高,判断过多.

简单工厂代码如下: 

package com.hjm.shd.shardingspheredemo.designPatterns.design2;


//抽象产品
interface Food{
    void eat();
}
//具体产品
class Hamburger implements Food {

    @Override
    public void eat() {
        System.out.println("吃汉堡");
    }
}
//具体产品
class RiceNoodle implements Food {

    @Override
    public void eat() {
        System.out.println("吃米线");
    }
}
//工厂
 class FoodFactory{
    public static Food getFood(int n){
        Food food = null;
        switch (n){
            case 1:
                food = new Hamburger();
                break;
            case 2:
                food = new RiceNoodle();
                break;
        }
        return food;
    }
}

//简单工厂模式
//简单工厂模式适用于,具体产品不多,且产品不经常变化的场景,如果具体产品很多,会导致工厂很臃肿
public class SimpleFactory {
    public static void main(String[] args) {
        Food food = FoodFactory.getFood(2);
        food.eat();
    }


}

简单工厂缺点:

当变化来了,客户端需要扩展具体产品的时候,势必需要修改简单工厂中的代码,这样违反了"开闭原则"

2.工厂方法模式

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

工厂方法代码如下:

package com.hjm.shd.shardingspheredemo.designPatterns.design2;

//抽象产品
interface Food{
    void eat();
}
//具体产品
class Hamburger3 implements Food{

    @Override
    public void eat() {
        System.out.println("吃汉堡");
    }
}
//具体产品
class RiceNoodle implements Food{

    @Override
    public void eat() {
        System.out.println("吃米线");
    }
}
//抽象工厂
interface FoodFactory{
    public Food getFood();
}
//具体工厂
class HamburgerFactory implements FoodFactory{

    @Override
    public Food getFood() {
        return new Hamburger3();
    }
}
class RiceNoodleFactory implements FoodFactory{

    @Override
    public Food getFood() {
        return new RiceNoodle();
    }
}
//定义一个品尝的方法
class Bussiness{
    public static void taste(FoodFactory foodFactory){
        Food food = foodFactory.getFood();
        food.eat();
    }
}



public class FactoryMethod {

    //测试
    public static void main(String[] args) {
        Bussiness.taste(new HamburgerFactory());
        Bussiness.taste(new RiceNoodleFactory());
    }

}

工厂方法模式缺点:

虽然此种方法解决了简单工厂,每次扩展都需要修改工厂的问题,但是如果业务种类过多,会产生大量的工厂,不利于后续维护.同时如果工厂的名字进行了修改,客户端还需要跟着修改(工厂的名字修改的概率毕竟小于产品名修改的概率).
 

3.抽象工厂模式

抽象工厂模式:将简单工厂和工厂方法结合,将工厂抽象为一个(可以有多个抽象方法),解决工厂方法在有多个产品簇时工厂过多问题.比如(食品,饮料,甜品等等)

抽象工厂代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design2;


//抽象工厂
interface Factory{
    public Food getFood();
    public Drink getDrink();
}

//抽象产品
interface Food{
    void eat();
}
interface Drink{
    void drink();
}
//具体产品
class Hamburger implements Food{

    @Override
    public void eat() {
        System.out.println("吃汉堡");
    }
}
//具体产品
class RiceNoodle implements Food{

    @Override
    public void eat() {
        System.out.println("吃米线");
    }
}
class Cola implements Drink{

    @Override
    public void drink() {
        System.out.println("喝可乐");
    }
}
class Sprite implements Drink{

    @Override
    public void drink() {
        System.out.println("喝雪碧");
    }
}

//具体工厂
class KFCFactory implements Factory{

    @Override
    public Food getFood() {
        return new Hamburger();
    }

    @Override
    public Drink getDrink() {
        return new Cola();
    }
}
class MDLFactory implements Factory{

    @Override
    public Food getFood() {
        return new RiceNoodle();
    }

    @Override
    public Drink getDrink() {
        return new Sprite();
    }
}
//定义一个品尝的方法
class Bussiness{
    public static void taste(Factory factory){
        Food food = factory.getFood();
        food.eat();
        Drink drink = factory.getDrink();
        drink.drink();
    }
}

public class abstractFactory {
    public static void main(String[] args) {
        Bussiness.taste(new KFCFactory());
        Bussiness.taste(new MDLFactory());
    }


}

抽象工厂缺点:

当产品等级发生变化时(增加产品等级或者删除产品等级),都要引起所有以前工厂代码的修改.违反了开闭原则.

 注意:不同老师讲解的抽象工厂与工厂方法略有不同,这里采取其中一种老师的讲法,有的老师在工厂方法讲解时,采用继承抽象类,抽象类的名称不叫xxxfactory(但做的确实是工厂的事情),在讲解抽象工厂的时候采用实现抽象接口(接口名称叫xxxfactory)

此处附上另一种讲解方法图:

产品等级含义:

工厂模式总结:

如果产品等级固定,可以使用抽象工厂

如果产品经常扩展 ,可以使用工厂方法

如果产品不扩充,简单工厂最好

在创建对象实例时,不要直接new出来,而是把new的动作放到工厂中,不要让类继承具体类,而是继承抽象类或者实现接口.

工厂模式在JDK中的应用:

在jdk Calendar中使用了简单工厂模式(静态工厂)如图:

原型模式:

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象.

使用场景:

1.克隆羊问题,通过一只羊克隆出其他羊

2.oa系统中周报模版,员工需要写本周内容,以及下周计划,大部分都不变,只变一小部分,员工可以保存上周模版,下周只修改一小部分.

3.同赛道产品迭代开发,大部分都相同,只有小部分不同(特殊处理)

浅拷贝:对与数据类型是基本数据类型的成员变量,浅拷贝会直接进行传递,也就是把该属性的值复制一份给新对象,对于数据类型是引用数据类型的成员变量,只是把原内容的内存地址给了新对象(拷贝后内存地址一致,修改一个会影响另一个).

深拷贝:复制对象的所有基本数据类型的成员变量值,为所有的引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量(修改克隆后的不会影响原来的).

深拷贝的实现方式有两种:

1.重写clone方法

2.实现序列化接口

原型模式代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design3;

import java.io.Serializable;

public class DeepCloneableTarget implements Serializable, Cloneable {

	private static final long serialVersionUID = 1L;

	private String cloneName;

	private String cloneClass;

	//构造器
	public DeepCloneableTarget(String cloneName, String cloneClass) {
		this.cloneName = cloneName;
		this.cloneClass = cloneClass;
	}

	//因为该类的属性,都是String , 因此我们这里使用默认的clone完成即可
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design3;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DeepProtoType implements Serializable, Cloneable{
	
	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();

		return deepProtoType;
	}
	
	//深拷贝 - 方式2 通过对象的序列化实现 (推荐)
	//先写入内存,在从内存读出来
	
	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) {
			e.printStackTrace();
			return null;
		} finally {
			//关闭流
			try {
				bos.close();
				oos.close();
				bis.close();
				ois.close();
			} catch (Exception e2) {
				System.out.println(e2.getMessage());
			}
		}
		
	}
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design3;

public class Client {

	public static void main(String[] args) throws Exception {
		DeepProtoType p = new DeepProtoType();
		p.name = "宋江";
		p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");
		
		//方式1 完成深拷贝
		
//		DeepProtoType p2 = (DeepProtoType) p.clone();
//		
//		System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
//		System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
	
		//方式2 完成深拷贝
		DeepProtoType p2 = (DeepProtoType) p.deepClone();
		
		System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
		System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
	
	}

}

原型模式在spring中的应用:

<!--  这里我们的 scope="prototype" 即 原型模式来创建  -->
<bean id="id01" class="com.atguigu.spring.bean.Monster" scope="prototype"/>

原型模式的缺点:

需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了开闭(ocp)原则

建造者模式:

建造者模式:又叫生成器模式,是一种对象构建模式,它可以将复杂对象的建造过程抽象查出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现对象.

使用场景:

适用于大部分流程都是不变的,只需要添加修饰的场景

1.盖房子,大部分步骤都固定,例如:打桩、砌墙、封顶.

2.组装电脑,例如:组装cpu、组装gpu、组装内存、组装固态.

建造者模式的四个角色:

1.product(产品角色):一个具体的产品对象

2.builder(抽象建造者):建造一个产品的抽象步骤,通常为接口或者抽象类,需要有一个返回产品的方法

3.concreteBuilder(具体建造者):实现接口,构建和装配各个部件,组合产品对象.

4.Director(指挥者):构建一个使用builder接口的对象,它主要用于创建一个复杂的对象.它主要是用于创建一个复杂的对象.它的作用有两个:一是:隔离客户与对象的产生过程,二是:负责控制产品对象的生产过程.

建造者模式代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design4;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
//电脑类
class Computer{
    private String cpu;
    private String gpu;
    private String memery;
    private String hd;
}
//电脑组装者
interface ComputerBuilder{
    void setCpu();
    void setGpu();
    void setMemery();
    void setHd();
    Computer build();
}
//组装高配版电脑
class AdvancedComputerBuilder implements ComputerBuilder{
    private Computer computer = new Computer();
    @Override
    public void setCpu() {
        computer.setCpu("i7");
    }

    @Override
    public void setGpu() {
        computer.setGpu("256G");
    }

    @Override
    public void setMemery() {
        computer.setMemery("1T");
    }

    @Override
    public void setHd() {
        computer.setHd("成功");
    }

    @Override
    public Computer build() {
        return computer;
    }
}
//组装低配版电脑
class LowComputerBuilder implements ComputerBuilder{
    private Computer computer = new Computer();
    @Override
    public void setCpu() {
        computer.setCpu("i5");
    }

    @Override
    public void setGpu() {
        computer.setGpu("128G");
    }

    @Override
    public void setMemery() {
        computer.setMemery("0.5T");
    }

    @Override
    public void setHd() {
        computer.setHd("成功2");
    }

    @Override
    public Computer build() {
        return computer;
    }
}
//指挥者
class Director{
    public Computer build(ComputerBuilder cb){
        cb.setCpu();
        cb.setGpu();
        cb.setMemery();
        cb.setHd();
        return cb.build();
    }
}
//客户端测试
public class Test1 {
    public static void main(String[] args) {
    AdvancedComputerBuilder acb = new AdvancedComputerBuilder();
    LowComputerBuilder lcb = new LowComputerBuilder();

        Director director = new Director();
        //高配
        Computer c = director.build(acb);
        System.out.println(c);

        //低配
        Computer c2 = director.build(lcb);
        System.out.println(c2);
    }
}

建造者模式的优点:

1.创建对象的过程是稳定不变的(因为有ComputerBuilder接口来稳定过程)

2.创建对象的过程只写了一次,没有重复代码(指挥者完成)

3.当需要扩展指挥者的时候,不用修改之前的代码,符合开闭原则

建造者模式和工厂模式的区别:

工厂模式只需要new一个产品即可,建造者模式更注重在new出产品后的,为产品属性赋值的过程.

建造者模式在JDK中的应用:

在StringBuilder源码中:

Appendable接口定义了多个append方法(抽象方法),即Appendable为抽象建造者,定义了抽象方法.

AbstractStringBuilder实现了Appendable接口方法,这里的AbstractStringBuilder已经是建造者,只是不能实例化

StringBuilder即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由AbstractStringBuilder完成,而StringBuilder继承了AbstractStringBuilder.

至此,23中设计模式中创建型模型全部已经整理完毕,接下来整理结构型模型,最后整理行为型模型.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值