小标
2019-05-09
来源 :
阅读 887
评论 0
摘要:本文主要向大家介绍了JAVA语言之创建型设计模式,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。
本文主要向大家介绍了JAVA语言之创建型设计模式,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

创建型设计模式成员
工厂方法模式
抽象工厂模式
建造者模式
原型模式
单例模式
1. 简单工厂模式
1.1 定义
简单工厂模式(Simple Factory Pattern):它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类
1.2 角色组成
Factory:工厂角色
Product:抽象产品角色
ConcreteProduct:具体产品角色
1.2.1 工厂角色Factory
SimpleFactory提供getMilk(String name)方法, 只需要告诉简单工厂牛奶品牌名称, 就能获得对应的牛奶
package com.zhunongyun.spring.springpattern.factory.simple;
import com.zhunongyun.spring.springpattern.factory.Mengniu;
import com.zhunongyun.spring.springpattern.factory.Milk;
import com.zhunongyun.spring.springpattern.factory.Telunsu;
import com.zhunongyun.spring.springpattern.factory.Yili;
public class SimpleFactory {
public Milk getMilk(String name){
Milk milk = null;
switch (name) {
case "特仑苏":
milk = new Telunsu();
break;
case "伊利":
milk = new Yili();
break;
case "蒙牛":
milk = new Mengniu();
break;
default:
System.out.println("不能生产您所需的产品");
break;
}
return milk;
}
}
### 1.2.2 抽象产品角色Product
> 抽象产品类Milk, 定义产品的属性, 具体产品都需要实现其属性
package com.zhunongyun.spring.springpattern.factory;
public interface Milk {
/**
获取一个标准产品
@return
*/
public String getName();
}
1.2.3 具体产品角色ConcreteProduct
具体产品类SanLu, YiLi, Telunsu是具体的产品, 需要实现抽象产品类Milk
YiLi:
package com.zhunongyun.spring.springpattern.factory;
public class Yili implements Milk {br/>@Override<br <="" a="">public String getName() {
return "伊利";
}
}
Telunsu:
package com.zhunongyun.spring.springpattern.factory;
public class Telunsu implements Milk {br/>@Override<br <="" a="">public String getName() {
return "特仑苏";
}
}
SanLu:
package com.zhunongyun.spring.springpattern.factory;
public class Sanlu implements Milk{br/>@Override<br <="" a="">public String getName() {
return "三鹿";
}
}
### 1.2.4 测试
package com.zhunongyun.spring.springpattern.factory.simple;
public class SimpleFactoryTest {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
//把用户的需求告诉工厂,需要用户提供具体产品的名称等信息,用户把产品创建交给工厂处理
System.out.println(factory.getMilk("AAA"));
System.out.println(factory.getMilk("蒙牛"));
}
}
输出:
不能生产您所需的产品
null
com.zhunongyun.spring.springpattern.factory.Mengniu@129a8472
## 1.3 总结
由工厂, 抽象产品, 具体产品三个角色组成,用户需要向工厂提供产品名称信息,创建其中的一款产品, 新增产品需要增加新的具体产品,工厂也需要修改
# 2. 工厂方法模式
## 2.1 定义
工厂模式方法(factory method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类
## 2.2 角色组成
* 抽象工厂
* 具体工厂
* 抽象产品
* 具体产品
### 2.2.1 抽象工厂
package com.zhunongyun.spring.springpattern.factory.func;
import com.zhunongyun.spring.springpattern.factory.Milk;
public interface Factory {
//工厂必然具有生产产品技能,统一的产品出口
Milk getMilk();
}
### 2.2.2 具体工厂
MengniuFactory:
package com.zhunongyun.spring.springpattern.factory.func;
import com.zhunongyun.spring.springpattern.factory.Mengniu;
import com.zhunongyun.spring.springpattern.factory.Milk;
public class MengniuFactory implements Factory {br/>@Override<br <="" a="">public Milk getMilk() {
return new Mengniu();
}
}
SanluFactory:
package com.zhunongyun.spring.springpattern.factory.func;
import com.zhunongyun.spring.springpattern.factory.Milk;
import com.zhunongyun.spring.springpattern.factory.Sanlu;
public class SanluFactory implements Factory {br/>@Override<br <="" a="">public Milk getMilk() {
return new Sanlu();
}
}
TelunsuFactory:
package com.zhunongyun.spring.springpattern.factory.func;
import com.zhunongyun.spring.springpattern.factory.Milk;
import com.zhunongyun.spring.springpattern.factory.Telunsu;
public class TelunsuFactory implements Factory {
@Override
public Milk getMilk() {
return new Telunsu();
}
}
### 2.2.3 抽象产品
package com.zhunongyun.spring.springpattern.factory;
public interface Milk {
/**
获取一个标准产品
@return
*/
public String getName();
}
2.2.4 具体产品
YiLi:
package com.zhunongyun.spring.springpattern.factory;
public class Yili implements Milk {
@Override
public String getName() {
return "伊利";
}
}
Telunsu:
package com.zhunongyun.spring.springpattern.factory;
public class Telunsu implements Milk {
@Override
public String getName() {
return "特仑苏";
}
}
SanLu:
package com.zhunongyun.spring.springpattern.factory;
public class Sanlu implements Milk{
@Override
public String getName() {
return "三鹿";
}
}
2.2.5 测试
package com.zhunongyun.spring.springpattern.factory.func;
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new SanluFactory();
System.out.println(factory.getMilk());
}
}
输出:
com.zhunongyun.spring.springpattern.factory.Sanlu@1b0375b3
2.3 总结
在工厂方法模式下,如果要增加产品,只需要扩展对应的具体工厂(ConcreteCreator)和具体产品(ConcreteProduct)即可,原有源码无需改变,遵循了“开闭原则”
用户需要某款产品只需要实例化对应的产品,此时没有创建产品,只要当需要使用时才会创建产品,用户在使用时都是以方法的事情操作产品
3. 抽象工厂模式
3.1 定义
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
3.2 角色组成
抽象工厂
具体工厂
抽象产品
具体产品
3.2.1 抽象工厂
package com.zhunongyun.spring.springpattern.factory.abstr;
import com.zhunongyun.spring.springpattern.factory.Milk;
public abstract class AbstractFactory {
//公共的逻辑
//方便于统一管理
/**
* 获得一个蒙牛品牌的牛奶
* @return
*/
public abstract Milk getMengniu();
/**
* 获得一个伊利品牌的牛奶
* @return
*/
public abstract Milk getYili();
/**
* 获得一个特仑苏品牌的牛奶
* @return
*/
public abstract Milk getTelunsu();
public abstract Milk getSanlu();
}
3.2.2 具体工厂
package com.zhunongyun.spring.springpattern.factory.abstr;
import com.zhunongyun.spring.springpattern.factory.*;
public class MilkFactory extends AbstractFactory {
@Override
public Milk getMengniu() {
return new Mengniu();
}
@Override
public Milk getYili() {
return new Yili();
}
@Override
public Milk getTelunsu() {
return new Telunsu();
}
@Override
public Milk getSanlu() {
return new Sanlu();
}
}
3.3.3 测试
package com.zhunongyun.spring.springpattern.factory.abstr;
public class AbstractFactoryTest {
public static void main(String[] args) {
MilkFactory factory = new MilkFactory();
//对于用户而言,更加简单了
//用户只有选择的权利了,保证了程序的健壮性
System.out.println(factory.getSanlu());
}
}
输出:
com.zhunongyun.spring.springpattern.factory.Sanlu@1b0375b3
3.4 总结
抽象工厂模式,定义了一个抽象工厂,抽象工厂中定义了创建对象的接口,由实现类实现对象创建,用户在使用时,只需要实例化抽象工厂,就能通过接口获取对象
4. 单例模式
4.1 定义
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。保证一个类仅有一个实例,并提供一个访问它的全局访问点
4.2 单例模式的几种实现方式
4.2.1 懒汉式
这种方式是lazy初始化,第一次调用才初始化,避免内存浪费, 多线程时为了保证线程安全需要加锁
线程不安全:
package com.zhunongyun.spring.springpattern.singleton;
public class Lazy {
private static Lazy instance;
private Lazy (){}
public static Lazy getInstance() {
if (instance == null) {
instance = new Lazy();
}
return instance;
}
}
线程安全:
package com.zhunongyun.spring.springpattern.singleton;
public class Lazy {
private static Lazy instance;
private Lazy (){}
public static synchronized Lazy getInstance() {
if (instance == null) {
instance = new Lazy();
}
return instance;
}
}
4.2.2 饿汉式
这种方式,类加载时就初始化,浪费内存,基于classloader机制避免了多线程的同步问题, 多线程下是安全的
package com.zhunongyun.spring.springpattern.singleton;
public class Hungry {
private static Hungry instance = new Hungry();
private Hungry(){}
public static Hungry getInstance() {
return instance;
}
}
4.2.3 双重校验锁
这种方式采用双锁机制,安全且在多线程情况下能保持高性能
package com.zhunongyun.spring.springpattern.singleton;
public class DoubleCheckedLocking {
private volatile static DoubleCheckedLocking singleton;
private DoubleCheckedLocking() {
}
public static DoubleCheckedLocking getSingleton() {
if (singleton == null) {
synchronized (DoubleCheckedLocking.class) {
if (singleton == null) {
singleton = new DoubleCheckedLocking();
}
}
}
return singleton;
}
}
4.2.4 登记式/静态内部类
这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用
这种方式同样利用了classloader机制来保证初始化instance时只有一个线程,SingletonHolder类没有被主动使用,只有通过显式调用getInstance方法时,才会显式装载SingletonHolder类,从而实例化instance
package com.zhunongyun.spring.springpattern.singleton;
public class Register {
private static class SingletonHolder {
private static final Register INSTANCE = new Register();
}
private Register() {
}
public static final Register getInstance() {
return SingletonHolder.INSTANCE;
}
}
4.2.5 枚举
这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化
package com.zhunongyun.spring.springpattern.singleton;
/**
* 数据库连接
*/
public class DBConnection {
}
package com.zhunongyun.spring.springpattern.singleton;
public enum DataSourceEnum {
DATASOURCE;
private DBConnection connection = null;
private DataSourceEnum() {
connection = new DBConnection();
}
public DBConnection getConnection() {
return connection;
}
}
package com.zhunongyun.spring.springpattern.singleton;
public class DataSourceEnumTest {
public static void main(String[] args) {
DBConnection con1 = DataSourceEnum.DATASOURCE.getConnection();
DBConnection con2 = DataSourceEnum.DATASOURCE.getConnection();
System.out.println(con1 == con2);
}
}
输出:
true
结果表明两次获取返回了相同的实例
Java规范中规定,每一个枚举类型极其定义的枚举变量在JVM中都是唯一的,因此在枚举类型的序列化和反序列化上,Java做了特殊的规定
在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过 java.lang.Enum 的valueOf()方法来根据名字查找枚举对象
也就是说,以下面枚举为例,序列化的时候只将DATASOURCE这个名称输出,反序列化的时候再通过这个名称,查找对于的枚举类型,因此反序列化后的实例也会和之前被序列化的对象实例相同
枚举会是线程安全、序列化与反序列化是相同的实例
4.3 总结
一般情况下,不建议使用4.2.1懒汉方式,建议使用4.2.2饿汉方式。只有在要明确实现lazy loading效果时,才会使用4.2.4登记方式。如果涉及到反序列化创建对象时,可以尝试使用4.2.5枚举方式。如果有其他特殊的需求,可以考虑使用4.2.3双检锁方式
5. 原型模式
5.1 定义
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用
5.2 序列化和反序列化
5.2.1 序列化和反序列化的概念
序列化: 把对象转换为字节序列的过程称为对象的序列化
反序列化: 把字节序列恢复为对象的过程称为对象的反序列化
对象的序列化主要有两种用途:
1 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2 在网络上传送对象的字节序列。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象
5.2.2 Serializable接口类
在JDK库中只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式
package com.zhunongyun.spring.prototype;
import lombok.Data;
import java.io.Serializable;
/**
* 测试对象序列化和反序列化
*/
@Data
public class Person implements Serializable {
/**
* 序列化ID
*/
private static final long serialVersionUID = -5809782578272943999L;
private int age;
private String name;
private String sex;
}
5.2.3 serialVersionUID的作用
serialVersionUID字面意思上是序列化的版本号,凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量
private static final long serialVersionUID = -5809782578272943999L;
两种生成方式:
1 default serial version ID
2 generated serial version ID
// default serial version ID
private static final long serialVersionUID = 1L;
// generated serial version ID
private static final long serialVersionUID = 4603642343377807741L;
那么serialVersionUID(序列化版本号)到底有什么用呢,我们用如下的例子来说明一下serialVersionUID的作用,看下面的代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TestSerialversionUID {
public static void main(String[] args) throws Exception {
SerializeCustomer();// 序列化Customer对象
Customer customer = DeserializeCustomer();// 反序列Customer对象
System.out.println(customer);
}
/**
* MethodName: SerializeCustomer
* Description: 序列化Customer对象
* @author xudp
* @throws FileNotFoundException
* @throws IOException
*/
private static void SerializeCustomer() throws FileNotFoundException,
IOException {
Customer customer = new Customer("gacl",25);
// ObjectOutputStream 对象输出流
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
new File("E:/Customer.txt")));
oo.writeObject(customer);
System.out.println("Customer对象序列化成功!");
oo.close();
}
/**
* MethodName: DeserializeCustomer
* Description: 反序列Customer对象
* @author xudp
* @return
* @throws Exception
* @throws IOException
*/
private static Customer DeserializeCustomer() throws Exception, IOException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
new File("E:/Customer.txt")));
Customer customer = (Customer) ois.readObject();
System.out.println("Customer对象反序列化成功!");
return customer;
}
}
/**
* <p>ClassName: Customer<p>
* <p>Description: Customer实现了Serializable接口,可以被序列化<p>
* @author xudp
* @version 1.0 V
* @createTime 2014-6-9 下午04:20:17
*/
class Customer implements Serializable {
//Customer类中没有定义serialVersionUID
private String name;
private int age;
public Customer(String name, int age) {
<span cla
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号