java初学,整理的也很是简陋,只是为了加强记忆,不喜勿喷,但是有误尽量指出。
Java设计模式
主要是创建型模式的学习,太渣,其他几个模式还没敢看。
Write Ahead:设计模式几大原则
a、Open Close Principle,即对扩展开放,对修改关闭,使得程序有好的扩展性,为了达到这样一个效果,需要使用接口和抽象类。
b、Dependence Inversion Principle,是Open Close Principle的基础,针对接口编程,依赖接口而不依赖于具体。
c、Liskov Substitution Principle,
d、Interface Segregation Principle,
e、Demeter Principle,
f、Composite Reuse Principle,
一、创建型模式:
- 工厂方法模式(Factory Method):大量对象,共同接口--普通工厂模式,多个工厂模式以及静态工厂模式
共同接口
public interface Sender {
void send();
}
多个对象:对象一
public class MailSender implements Sender {
@Override
public void send() {
System.out.println("I am mail sender!");
}
}
多个对象:对象二
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("I am sms sender!");
}
}
11、普通工厂模式
public class SendFactory {
public Sender produce(String type){
if("mail".equals(type)){
return new MailSender();
}
if("sms".equals(type)){
return new SmsSender();
}
else
System.out.println("请输入正确的类型!");
return null;
}
}
12、多个工厂模式
public class MultiFactory{
public Sender produceMail(){
return new MailSender();
}
public Sender produceSms(){
return new SmsSender();
}
}
13、静态工厂模式,不需要创建实例
public class StaticFactory{
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
缺点:只有一个工厂类,想要扩展程序必须对工厂类进行修改,因此类的创建依赖于工厂类,这违背了闭包原则。所以有了抽象工厂模式。
- 抽象工厂模式:多个工厂,开闭原则,只加不修改
提供一个工厂接口,即抽象工厂
public interface Provider {
Sender produce();
}
多个工厂:工厂一
public class MailFactory implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
多个工厂:工厂二
public class SmsFactory implements Provider {
@Override
public Sender produce() {
return new SmsSender();
}
}
优点:想要新增一个发即时消息的功能,只需一个实现Sender接口的实现类和一个实现provider接口的实现类即可,避免修改现有代码。 - 单例模式(Singleton),在一个JVM中,某对象只有一个实例存在。
a、有些类的创建比较频繁,对于大型对象,是很大的系统开销。
b、省去了new操作符,降低了系统内存的使用频率,减轻GC(Garbage Collection)压力。
c、有些类控制着整个流程(例如某交易所的核心交易引擎控制着交易流程),如果该类允许创建多个的话,整个系统就完全乱了。
单例模式必须保证线程安全
1⃣️饿汉式:线程安全,但是类加载时就实例化,而且由于构造函数私有,无法继承
public class Singleton {
/**- 类加载时自行实例化
/
private static final Singleton instance = new Singleton();
/* - 私有构造函数
/
private Singleton(){
}
/* - 唯一外部可访问接口,线程安全
/
public static Singleton getInstance(){
return instance;
}
}
2⃣️懒汉式:存在线程安全的问题
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){
}
/* - 非线程安全
/
public static LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
3⃣️线程安全的懒汉式:效率低
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){
}
/* - 加锁,线程安全,效率低
/
public synchronized static LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
4⃣️双重校验锁-线程安全锁懒汉式:由于JVM内存模型,无序优化,导致双重验证锁问题(DCL,Double-checked-locked)
public class LazySingletonDoubleChecked {
private static LazySingletonDoubleChecked instance;
/私有构造函数/
private LazySingletonDoubleChecked(){
}
/双重检查加锁的代码/
public static LazySingletonDoubleChecked getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance = new LazySingletonDoubleChecked();
}
}
}
return instance;
}
}
/*
- 类加载时自行实例化
- 1.线程1进入getInstance() 方法。
- 2.由于此时instance 为null,线程1进入synchronized 块。
- 3.此时线程1被线程2预占。
- 4.线程2进入getInstance()方法。
- 5.由于此时instance仍null,线程2试图获取锁。由于线程1持有该锁,线程2将进入阻塞。
- 6.线程2被线程1预占,线程1执行
- 7.由于实例仍为null,线程1创建一个LazySingletonDoubleChecked对象并将其引用赋值给instance。
- 8.线程1退出synchronized块并从getInstance() 方法返回实例。
- 9.线程1被线程2预占。
- 10.线程2获取锁并检查instance是否为null。
- 11.由于instance非null的,就咩有创建第二个Singleton对象,由线程1创建的一个尚未执行构造函数的对象被返回。
- 假设为代码行instance =new LazySingletonDoubleChecked(); 执行了下列伪代码:
- memory = allocate(); //为LazySingletonDoubleChecked对象分配memory.
- instance = memory; //此时instance不是null, 但是并没有被initialized.
- constructorSingleton(instance);//Invoke constructor进行初始化.
/
5⃣️volatile-双重校验锁-线程安全锁懒汉式:
public class LazySingletonDoubleChecked {
private volatile static LazySingletonDoubleChecked instance;
/私有构造函数/
private LazySingletonDoubleChecked(){
}
/双重检查加锁的代码/
public static LazySingletonDoubleChecked getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance = new LazySingletonDoubleChecked();
}
}
}
return instance;
}
}
下面只需要对initialized对象进行加锁,缩小了锁的范围
public class LazySingletonDoubleChecked {
private volatile static LazySingletonDoubleChecked instance = null;
private Boolean initialized = false;
public LazySingletonDoubleChecked getInstance(){
if(!initialized){
synchronized (initialized){
if(instance == null){
instance = new LazySingletonDoubleChecked();
}
initialized = true;
return instance;
}
}
return instance;
}
}
6⃣️枚举式:
7⃣️登记式-懒汉式单例:6⃣️7⃣️暂不研究
使用内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的过程是线程互斥的。这样第一次调用getInstance时,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕
public class SingletonInnerClass {
private SingletonInnerClass(){
}
/*
*使用内部类来维护单例的实现
/
private static class SingletonFactory{
private static SingletonInnerClass instance = new SingletonInnerClass();
}
public static SingletonInnerClass getInstance(){
return SingletonFactory.instance;
}
/ 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */
public Object readResolve() {
return getInstance();
}
}
-
建造者模式(Builder Method):创建复合类型,相对于工厂模式,将多个功能集合到一个类中
public class Builder {
List<Sender> list = new ArrayList<Sender>();public void produceMailSender(){
list.add(0, new MailSender());
}public void produceSmsSender(){
list.add(0, new SmsSender());
}
} -
原型模式(Prototype Method):一个对象作为原型,对其进行克隆,复制产生一个和原对象类似的新对象
只需要实现Cloneable接口,覆写clone方法
public class Prototype implements Cloneable {@Override
public Object clone() throws CloneNotSupportedException {
/**
* super.clone()调用的是object.clone方法(native)
*/
Prototype proto = (Prototype) super.clone();
return proto;
}
}
浅复制:浅复制不彻底。基本数据类型的变量重新创建,而引用类型指向原对象所指向的内存。
深复制:就是深复制进行了完全彻底的复制。将一个对象复制后,基本数据类型和引用类型,都重新创建。
public class Prototype implements Cloneable, Serializable {private static final long serialVersionUID = 1L;
private String str;private SerializableObject serializableObject;
/* 浅复制 */
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}/* 深复制 */
public Object deepClone() throws IOException, ClassNotFoundException {/* 写入当前对象的二进制流 */ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); /* 读出二进制流产生的新对象 */ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject();
}
public String getStr() {
return str;
}public SerializableObject getSerializableObject() {
return serializableObject;
}public void setStr(String str) {
this.str = str;
}public void setSerializableObject(SerializableObject serializableObject) {
this.serializableObject = serializableObject;
}
}
class SerializableObject implements Serializable {
private static final long serialVersionUID = 1L;
}
二、结构型模式:
三、行为型模式: