赞
踩
在软件开发的历程中,正是无数前辈们本着追求完美的架构设计和代码设计的初心。经过无数前辈们的探索和努力,逐渐形成了一系列的设计原则和设计模式。
对于Java语言来说,通常包含有6大设计原则和23中设计模式。这些都是前辈们对于开发思想的结晶。我们学习和理解这些设计原则和设计模式,深入掌握其实现原理和使用场景,能够更好的设计我们的系统架构。编写出具有高性能、高并发、高可用、高可扩展性和高可维护性的代码。
在Java的常见的23种设计模式中,大体上可以分为创建型模式、结构型模式和行为型模式三大类。本系列文章就对Java中的23种设计模式进行汇总,方便记录和查阅。
LSP
是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受影响时,基类才能真正被复用,衍生类也能够在基类的基础上增加新的行为看几个单例对象的示例代码,其中有些代码是线程安全的,有些则不是线程安全的,需要大家细细品味。
package com.cz.Creativemodel; /** * @Author: zhang * @Date: 2021/3/29 - 19:48 * @Descripetion: 懒汉模式,单例实例在第一次使用的时候进行创建,这个类是线程不安全的 **/ public class SingletonExample1 { private SingletonExample1(){ } private static SingletonExample1 instance = null; private static SingletonExample1 getInstance(){ //多个线程同时调用,可能会创建多个对象 if (instance == null){ instance = new SingletonExample1(); } return instance; } }
package com.cz.Creativemodel; /** * @Author: zhang * @Date: 2021/3/29 - 19:52 * @Descripetion: 饿汉模式,单例实例在类装载的时候进行创建,是线程安全的 **/ public class SingletonExample2 { private SingletonExample2(){} private static SingletonExample2 instance = new SingletonExample2(); public static SingletonExample2 getInstance(){ return instance; } }
package com.cz.Creativemodel; /** * @Author: zhang * @Date: 2021/3/29 - 19:54 * @Descripetion: 懒汉模式,单例实例在第一次使用的时候进行创建,这个类是线程安全的,但是这个写 法不推荐 **/ public class SingletonExample3 { private SingletonExample3(){} private static SingletonExample3 instance = null; public static synchronized SingletonExample3 getInstance(){ if (instance == null){ instance = new SingletonExample3(); } return instance; } }
package com.cz.Creativemodel; /** * @Author: zhang * @Date: 2021/3/29 - 19:57 * @Descripetion: 懒汉模式(双重锁同步锁单例模式) * 单例实例在第一次使用的时候进行创建,这个类不是线程安全的 **/ public class SingletonExample4 { private SingletonExample4(){} private static SingletonExample4 instance = null; public static SingletonExample4 getInstance(){ if (instance == null){ synchronized (SingletonExample4.class){ if (instance == null){ instance = new SingletonExample4(); } } } return instance; } }
线程不安全分析如下:
当执行instance = new SingletonExample4();
这行代码时,CPU会执行如下指令:
memory = allocate()
分配对象的内存空间ctorInstance()
初始化对象instance = memory
设置instance
指向刚分配的内存单纯执行以上三步没啥问题,但是在多线程情况下,可能会发生指令重排序。
指令重排序对单线程没有影响,单线程下CPU可以按照顺序执行以上三个步骤,但是在多线程下,如果发生了指令重排序,则会打乱上面的三个步骤。
如果发生了JVM
和CPU
优化,发生重排序时,可能会按照下面的顺序执行:
memory = allocate()
分配对象的内存空间instance = memory
设置instance
指向刚分配的内存ctorInstance()
初始化对象假设目前有两个线程A和B同时执行getInstance()
方法,A线程执行到instance = new SingletonExample4();
B线程刚执行到第一个if (instance == null){}
处,
如果按照1.3.2
的顺序,假设线程A执行到3.instance = memory
设置instance
指向刚分配的内存,此时,线程B判断instance
已经有值,就会直接return instance;
而实际上,线程A还未执行2.ctorInstance()
初始化对象,也就是说线程B拿到的instance
对象 还未进行初始化,这个未初始化的instance
对象一旦被线程B使用,就会出现问题。
例五:SingletonExample5
懒汉模式(双重锁同步锁单例模式)单例实例在第一次使用的时候进行创建,这个类是线程安全的,使用的是 volatile +
双重检测机制来禁止指令重排达到线程安全
package com.cz.Creativemodel; /** * @Author: zhang * @Date: 2021/3/29 - 20:06 * @Descripetion: 懒汉模式(双重锁同步锁单例模式) * 单例实例在第一次使用的时候进行创建,这个类是线程安全的 **/ public class SingletonExample5 { private SingletonExample5(){} //单例对象 volatile + 双重检测机制来禁止指令重排 private volatile static SingletonExample5 instance = null; public static SingletonExample5 getInstance(){ if (instance == null){ synchronized (SingletonExample5.class){ if (instance == null){ return instance = new SingletonExample5(); } } } return instance; } }
package com.cz.Creativemodel; /** * @Author: zhang * @Date: 2021/3/29 - 20:09 * @Descripetion: 饿汉模式,单例实例在类装载的时候进行创建,是线程安全的 **/ public class SingletonExample6 { private SingletonExample6(){} private static SingletonExample6 instance = null; static { instance = new SingletonExample6(); } public static SingletonExample6 getInstance(){ return instance; } }
package com.cz.Creativemodel; /** * @Author: zhang * @Date: 2021/3/29 - 20:11 * @Descripetion: 枚举方式进行实例化,是线程安全的,此种方式也是线程最安全的 **/ public class SingletonExample7 { private SingletonExample7(){} public static SingletonExample7 getInstance(){ return Singleton.INSTANCE.getInstance(); } private enum Singleton{ INSTANCE; private SingletonExample7 singleton; //JVM保证这个方法绝对只调用一次 Singleton(){ singleton = new SingletonExample7(); } public SingletonExample7 getInstance(){ return singleton; } } }
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。
为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new
,我们经常要根据类Class生成实例对象,如A a=new A()
工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量
AbstractFactory
声明一个创建抽象产品对象的操作接口。ConcreteFactory
实现创建具体产品对象的操作。AbstractProduct
为一类产品对象声明一个接口。ConcreteProduct
定义一个将被相应的具体工厂创建的产品对象。 实现AbstractProduct
接口。Client
仅使用由AbstractFactory
和AbstractProduct
类声明的接口AbstractFactory
:定义抽象工程类IAnimalFactory
package com.cz.Creativemodel.abstractfactory; /** * @Author: zhang * @Date: 2021/3/29 - 20:28 * @Descripetion: 这个接口就是类图中标识的AbstractFactory抽象工厂 **/ public interface IAnimalFactory { /** * 定义创建Icat接口实例的方法 * @return */ ICat createCat(); /** * 定义创建IDog接口实例的方法 * @return */ IDog createDog(); }
ConcreteFactory
:创建抽象工厂类的两个实现类,WhiteAnimalFactory
和BlackAnimalFactory
package com.cz.Creativemodel.abstractfactory; /** * @Author: zhang * @Date: 2021/3/29 - 20:31 * @Descripetion: IAnimalFactory抽象工厂的实现类 **/ public class WhiteAnimalFactory implements IAnimalFactory { @Override public ICat createCat() { return new WhiteCat(); } @Override public IDog createDog() { return new WhiteDog(); } }
package com.cz.Creativemodel.abstractfactory; /** * @Author: zhang * @Date: 2021/3/29 - 20:32 * @Descripetion: IAnimalFactory抽象工厂的实现类 **/ public class BlackAnimalFactory implements IAnimalFactory { @Override public ICat createCat() { return new BlackCat(); } @Override public IDog createDog() { return new BlackDog(); } }
AbstractProduct
:定义抽象工厂中要生产的抽象产品接口ICat
和IDog
package com.cz.Creativemodel.abstractfactory;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:34
* @Descripetion: 类图中定义的AbstractProduct
* 指定工厂生产的产品
**/
public interface ICat {
/**
* 定义方法
*/
void eat();
}
package com.cz.Creativemodel.abstractfactory;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:36
* @Descripetion: 类图中定义的AbstractProduct
* 指定工厂生产的产品
**/
public interface IDog {
/**
*定义方法
*/
void eat();
}
ConcreteProduct
:创建产品的实现类BlackCat
、BlackDog
、WhiteCat
、WhiteDog
package com.cz.Creativemodel.abstractfactory;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:37
* @Descripetion: ICat接口的实现类
**/
public class BlackCat implements ICat {
@Override
public void eat() {
System.out.println("The black cat is eating!");
}
}
package com.cz.Creativemodel.abstractfactory;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:38
* @Descripetion: IDog的实现类
**/
public class BlackDog implements IDog {
@Override
public void eat() {
System.out.println("The black dog is eating");
}
}
package com.cz.Creativemodel.abstractfactory;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:39
* @Descripetion: ICat的实现类
**/
public class WhiteCat implements ICat {
@Override
public void eat() {
System.out.println("The white cat is eating!");
}
}
package com.cz.Creativemodel.abstractfactory;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:39
* @Descripetion: IDog的实现类
**/
public class WhiteDog implements IDog {
@Override
public void eat() {
System.out.println("The white dog is eating!");
}
}
package com.cz.Creativemodel.abstractfactory; /** * @Author: zhang * @Date: 2021/3/29 - 20:43 * @Descripetion: 测试类 **/ public class Test { public static void main(String[] args) { IAnimalFactory blackAnimalFactory = new BlackAnimalFactory(); ICat blackCat = blackAnimalFactory.createCat(); blackCat.eat(); IDog blackDog = blackAnimalFactory.createDog(); blackDog.eat(); IAnimalFactory whiteAnimalFactory = new WhiteAnimalFactory(); ICat whiteCat = whiteAnimalFactory.createCat(); whiteCat.eat(); IDog whiteDog = whiteAnimalFactory.createDog(); whiteDog.eat(); } }
由此可见,工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他地方无需一点变换,就有可能将系统功能进行改头换面的变化
定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod
使一个类的实例化延迟到其子类。
Product
定义工厂方法所创建的对象的接口。ConcreteProduct
实现Product
接口。Creator
声明工厂方法,该方法返回一个Product
类型的对象。 Creator
也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct
对象。 可以调用工厂方法以创建一个Product
对象。ConcreteCreator
重定义工厂方法以返回一个ConcreteProduct
实例。package com.cz.Creativemodel.factorymethod;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:52
* @Descripetion: 定义一个接口Wo
**/
public interface Work {
/**
* 定义方法
*/
void doWork();
}
package com.cz.Creativemodel.factorymethod;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:52
* @Descripetion: Work接口的具体实现类
**/
public class TeacherWork implements Work {
@Override
public void doWork() {
System.out.println("老师审批作业!");
}
}
package com.cz.Creativemodel.factorymethod;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:53
* @Descripetion: Work接口的具体实现类
**/
public class StudentWork implements Work {
@Override
public void doWork() {
System.out.println("学生做作业!");
}
}
package com.cz.Creativemodel.factorymethod;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:54
* @Descripetion: 抽象工厂接口
**/
public interface IWorkFactory {
/**
* 定义获取Work实例对象的方法
* @return
*/
Work getWork();
}
package com.cz.Creativemodel.factorymethod;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:55
* @Descripetion: IWorkFactory工厂的实现类
**/
public class StudentWorkFactory implements IWorkFactory {
@Override
public Work getWork() {
return new StudentWork();
}
}
package com.cz.Creativemodel.factorymethod;
/**
* @Author: zhang
* @Date: 2021/3/29 - 20:56
* @Descripetion: IWorkFactory工厂的实现类
**/
public class TeacherWorkFactory implements IWorkFactory {
@Override
public Work getWork() {
return new TeacherWork();
}
}
package com.cz.Creativemodel.factorymethod; /** * @Author: zhang * @Date: 2021/3/29 - 21:00 * @Descripetion: 测试类 **/ public class Test { public static void main(String[] args) { IWorkFactory studentWorkFactory = new StudentWorkFactory(); studentWorkFactory.getWork().doWork(); IWorkFactory teacherWorkFactory = new TeacherWorkFactory(); teacherWorkFactory.getWork().doWork(); } }
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Builder
为创建一个Product
对象的各个部件指定抽象接口。ConcreteBuilder
实现Builder
的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示。提供一个检索产品的接口。Director
构造一个使用Builder
接口的对象。Product
表示被构造的复杂对象。ConcreteBuilder
创建该产品的内部表示并定义它的装配过程。包含定义组成部件的类,包括将这些部件装配成最终产品的接口。package com.cz.Creativemodel.builder;
/**
* @Author: zhang
* @Date: 2021/3/29 - 21:09
* @Descripetion: Person对象的构造接口
**/
public interface PersonBuilder {
void buildHead();
void buildBody();
void buildFoot();
Person buildPerson();
}
package com.cz.Creativemodel.builder; /** * @Author: zhang * @Date: 2021/3/29 - 21:12 * @Descripetion: Person对象的构造器 **/ public class ManBuilder implements PersonBuilder { Person person; public ManBuilder(){ person = new Man(); } @Override public void buildHead() { person.setHead("建造男人的头"); } @Override public void buildBody() { person.setBody("建造男人的身体"); } @Override public void buildFoot() { person.setFoot("建造男人的脚"); } @Override public Person buildPerson() { return person; } }
package com.cz.Creativemodel.builder; /** * @Author: zhang * @Date: 2021/3/29 - 21:15 * @Descripetion: Person对象的整体构造器 **/ public class PersonDirector { public Person constructPerson(PersonBuilder pb){ pb.buildHead(); pb.buildBody(); pb.buildFoot(); return pb.buildPerson(); } }
package com.cz.Creativemodel.builder; /** * @Author: zhang * @Date: 2021/3/29 - 21:17 * @Descripetion: Person对象 **/ public class Person { private String head; private String body; private String foot; public String getHead() { return head; } public void setHead(String head) { this.head = head; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getFoot() { return foot; } public void setFoot(String foot) { this.foot = foot; } }
package com.cz.Creativemodel.builder;
/**
* @Author: zhang
* @Date: 2021/3/29 - 21:18
* @Descripetion: 创建一个男人类继承Person
**/
public class Man extends Person {
}
package com.cz.Creativemodel.builder; /** * @Author: zhang * @Date: 2021/3/29 - 21:19 * @Descripetion: 描述 **/ public class Test { public static void main(String[] args) { PersonDirector pd = new PersonDirector(); Person person = pd.constructPerson(new ManBuilder()); System.out.println(person.getHead()); System.out.println(person.getBody()); System.out.println(person.getFoot()); } }
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
Prototype
声明一个克隆自身的接口。ConcretePrototype
实现一个克隆自身的操作。Client
让一个原型克隆自身从而创建一个新的对象。package com.cz.Creativemodel.prototype; /** * @Author: zhang * @Date: 2021/3/29 - 21:24 * @Descripetion: 原型类,实现Cloneable接口 **/ public class Prototype implements Cloneable { private String name; public void setName(String name){ this.name = name; } public String getName(){ return this.name; } public Object clone(){ try { return super.clone(); }catch (Exception e){ e.printStackTrace(); return null; } } }
package com.cz.Creativemodel.prototype;
/**
* @Author: zhang
* @Date: 2021/3/29 - 21:26
* @Descripetion: 原型类的子类,用于构建原型
**/
public class ConcretePrototype extends Prototype {
public ConcretePrototype(String name){
setName(name);
}
}
package com.cz.Creativemodel.prototype;
/**
* @Author: zhang
* @Date: 2021/3/29 - 21:28
* @Descripetion: 测试类
**/
public class Test {
public static void main(String[] args) {
Prototype prototype = new ConcretePrototype("prototype");
Prototype prototype1 = (Prototype)prototype.clone();
System.out.println(prototype.getName());
System.out.println(prototype1.getName());
}
}
创造型模式就讲完了;结构性模式和行为模式会在接下来的文章写
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。