今天给大家简单分享关于23设计模式:
总体来说设计模式分为三大类:
一、创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
二、结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
三、行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
本章主要详细 对创建模式这5种设计模式进行详解:
- 工厂方法模式
- 抽象工厂模式
- 单例模式
- 建造者模式
- 原型模式
普通工厂模式:
原理:就是建立一个工厂类,统一对实现了同一接口的一些类进行实例的创建。
//定义一个接口
public interface Delivery {
/**
* 单个
* @return
*/
public String Delivery();
}
编写实现类
public class A_Delivery implements Delivery {
@Override
public String Delivery() {
return "A - Delivery -is Sending ";
}
}
public class B_Delivery implements Delivery {
@Override
public String Delivery() {
return "B - Delivery -is Sending ";
}
}
创建普通工厂
/**
* 普通工厂类
* @author cjl
*
*/
public class NorFactory {
/**
* 普通单个工厂
* @param flag
* @return
*/
public Delivery sendSingleDelivery(int flag){
if (flag > 0) {
return new A_Delivery();
}
return new B_Delivery();
}
}
Test
public class testMain {
public static void main(String[] args) {
// 可以采用注解的方式进行计算
NorFactory nor = new NorFactory();
Delivery send=nor.sendSingleDelivery(3);
//调用
System.out.println(send.Delivery());
}
}
创建多个普通工厂
public class NorFactory {
//创建 针对A类物流发送的方法
public Delivery send_A_Delivery(){
return new A_Delivery();
}
//创建 针对B类物流发送的方法
public Delivery send_B_Delivery(){
return new B_Delivery();
}
}
Test
public class testMain {
public static void main(String[] args) {
// 可以采用注解的方式进行计算
NorFactory nor = new NorFactory();
Delivery sendA=nor.send_A_Delivery();
Delivery sendB=nor.send_B_Delivery();
System.out.println(sendA.Delivery());
System.out.println(sendB.Delivery());
}
}
创建静态工厂
public class NorFactory {
//创建 针对A类物流发送的方法
public static DeliverysendStatic_A_Delivery(){
return new A_Delivery();
}
//创建 针对B类物流发送的方法
public static Delivery sendStatic_B_Delivery(){
return new B_Delivery();
}
}
Test
public class testMain {
public static void main(String[] args) {
// 可以采用注解的方式进行计算
NorFactory nor = new NorFactory();
Delivery sendA=NorFactory.sendStatic_A_Delivery();
Delivery sendB=NorFactory.sendStatic_B_Delivery();
System.out.println(sendA.Delivery());
System.out.println(sendB.Delivery());
}
}
通过对比列子可以发现 普通工厂,多个普通工厂 ,静态工厂 这类特点如下:
1、多个普通工厂,静态工厂相比,普通工厂 而言不需要传递参数进行调用各个方法。只需要实例化就可以调用。
2、普通工厂,多个普通工厂 ,静态工厂 适用的场景:凡是出现了大量的产品需要创建,并且具有共同的接口功能时,可以通过工厂方法模式进行创建。
3、普通工厂,多个普通工厂 ,静态工厂缺点:拓展性相对较弱。比如 新增一个物流又新增一个功能C,norFactory工厂如果要整合C的功能的话,就必须修改代码才能实现通过norFactory调用C的功能。因此可以采用【抽象工厂】 如下的方法解决此类问题。
抽象工厂模式
抽象工厂模式特点:
- 每个具体工厂类可以创建多个具体产品类的实例
- 一个抽象工厂类,可以派生出多个具体工厂类
- 功能扩展性相比普通工厂模式要好点
如图:
//定义一个接口
public interface Delivery {
/**
* 单个
* @return
*/
public String Delivery();
}
编写实现类
public class A_Delivery implements Delivery {
@Override
public String Delivery() {
return "A - Delivery -is Sending ";
}
}
public class B_Delivery implements Delivery {
@Override
public String Delivery() {
return "B - Delivery -is Sending ";
}
}
创建抽象工厂类接口
public interface DeliveryProvider {
public Delivery handleProvider();
}
实现接口
@Service("A_Provider_Factory")
public class A_Provider_Factory implements DeliveryProvider {
//接口实现对A类物流数据的封装
@Override
public Delivery handleProvider() {
return new A_Delivery();
}
}
@Service("B_Provider_Factory")
public class B_Provider_Factory implements DeliveryProvider {
//接口实现对B类物流数据的封装
@Override
public Delivery handleProvider() {
return new B_Delivery();
}
}
Test
public static void main(String[] args) {
/*采用注解注释
@Autowired
@Qualifier("XXXXname")
private DeliveryProvider DeliveryProvider;
*/
DeliveryProvider DpA=new A_Provider_Factory();
Delivery Dps=DpA.handleProvider();
System.out.println(Dps.Delivery());
//采用注解注释
DeliveryProvider DpB=new B_Provider_Factory();
Delivery Dpsb=DpB.handleProvider();
System.out.println(Dpsb.Delivery());
}
建造者模式
将各种产品集中起来进行管理,用来创建复合对象。
/**
* 建造者模式
* @author cj
*
*/
public class BuildFactory {
private List<Delivery> tempList = new ArrayList<Delivery>();
// 创建A对应的数据格式
public void A_Provider_Builder(int a) {
for (int i = 0; i < a; i++) {
tempList.add(new A_Delivery());// 重复创建数据A
}
}
// 创建B对应的数据格式
public void B_Provider_Builder(int a) {
for (int i = 0; i < a; i++) {
tempList.add(new B_Delivery());// 重复创建数据B
}
}
}
Test
BuildFactory bf = new BuildFactory();
bf.A_Provider_Builder(4);
bf.B_Provider_Builder(3);
单例模式
目的:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式应该是23种设计模式中最简单的一种模式了。它有以下几个要素:
1. 私有的构造方法
2. 指向自己实例的私有静态引用
3. 以自己实例为返回值的静态的公有的方法
单例模式 通常分两种:饿汉模式 | 懒汉模式
饿汉模式:
/**
* 单例模式(饿汉单例模式)
* @author cjl
*
*/
public class SingleHungerClass {
//私有的构造方法
private SingleHungerClass(){
}
//方法1 指向自己实例的私有静态私有引用方法
private static SingleHungerClass sc=new SingleHungerClass();
//方法2
private static SingleHungerClass sc=null;
static{
sc=new SingleHungerClass();
}
//以自己为实例返回值的静态共有方法
public static SingleHungerClass getInstance(){
return sc;
}
}
方法1 和方法2 实现功能效果基本一样。饿汉式 需要注意的一点:当类被加载的的时候,会将实例化类返回给引用。
懒汉模式
**
* 懒汉单例模式
* @author cjl
*
*/
public class SingleLazyClass {
//定义一个私有构造函数
private SingleLazyClass(){
}
//定义一个指向自己实例的 的静态引用
private static SingleLazyClass slc= new SingleLazyClass();
// 方法 1定义一个以自己为返回值静态实例的静态方法 (获取当前实例方法的时候 才会获取对象)
private static synchronized SingleLazyClass getInstance(){
if (slc==null) {
return new SingleLazyClass();
}
return slc;
}
// 方法 2 优化方法1 这样不需要需要每次获取的方法的时候都获取对对象上锁。第一次的上锁就行
private static SingleLazyClass getBetterInstnace(){
if (slc==null) {
synchronized(slc){
if (slc==null) {
slc=new SingleLazyClass();
}
}
}
return slc;
}
}
方法 1 和方法2 区别是 方法2 是优化了方法1 的效果 ,懒汉实例化特点是 只有当前获取实例对象方法的时候,才会获取当前实例对象(方法1) ,但是大家注意 synchronized 并不是每次都需要调用方法的时候都需要synchronized ,其实只有第一次的时候就可以(方法2)。
懒汉模式 线程是不安全的如图:
- 1、2线程同时进入了第一个if判断
- 1首先进入synchronized块,由于instance为null,所以它执行slc= new SingleLazyClass();
- 由于JVM内部的优化机制,JVM先画出了一些分配给SingleLazyClass实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后1离开了synchronized块。
- 2进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序。
- 此时2线程打算使用SingleLazyClass实例,却发现它没有被初始化,于是错误发生了。
原型模式
原型模式 实际上是根据一个已知对象实例获取/创建/拷贝一个对象种类。主要用的是对象里面 Clone()|实现Cloneable方法。原型模式一个原型对象的clone方法可以复制原型对象到一个新的对象中。
定义一个基本类
/**
* 定义原型bean
* @author cjl
*
*/
public class Orign {
private String className;
private String classType;
public Orign(String className, String classType) {
super();
this.className = className;
this.classType = classType;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getClassType() {
return classType;
}
public void setClassType(String classType) {
this.classType = classType;
}
}
创建一个类
/**
* 原型模式
* @author cjl
*
* 1.继承Cloneable
* 2.复写clone()
*
*/
public class OrignFactory implements Cloneable{
private String classFactoryName;
private String classFactoryType;
private Orign orign;
private List<String> list=new ArrayList<String>();
//克隆 自己
@Override
public OrignFactory clone() throwsCloneNotSupportedException {
return (OrignFactory) super.clone();
}
//展示clone 数据
@Override
public String toString() {
return "className:"+this.classFactoryName+",classType:"+classFactoryType+",Orign-Name"+orign.getClassName() +",Orign-Type"+orign.getClassType()+ ",list-size:"+list.size();
}
public String getClassFactoryName() {
return classFactoryName;
}
public void setClassFactoryName(String classFactoryName) {
this.classFactoryName = classFactoryName;
}
public String getClassFactoryType() {
return classFactoryType;
}
public void setClassFactoryType(String classFactoryType) {
this.classFactoryType = classFactoryType;
}
public Orign getOrign() {
return orign;
}
public void setOrign(Orign orign) {
this.orign = orign;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public OrignFactory() {
}
public OrignFactory(String classFactoryName, String classFactoryType, Orign orign, List<String> list) {
super();
this.classFactoryName = classFactoryName;
this.classFactoryType = classFactoryType;
this.orign = orign;
this.list = list;
}
}
Test
@Test
// 调用抽象工厂
public void testOrgin() throws CloneNotSupportedException {
Orign or1=new Orign("O1","O2");
List<String> list=new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
OrignFactory nof=new OrignFactory("OF1","OF2",or1,list);
System.out.println(nof.toString());
System.out.println("------------复制------------------");
OrignFactory nof2=nof.clone();
System.out.println(nof2.toString());
Orign or2=new Orign("O3","O4");
System.out.println("-----------从新赋值----------------");
nof2.setOrign(or2);
nof2.getList().remove(3);
System.out.println(nof2.toString());
}
返回结果
className:OF1,classType:OF2,Orign-NameO1,Orign-TypeO2,list-size:4
-------------------------------
className:OF1,classType:OF2,Orign-NameO1,Orign-TypeO2,list-size:4
-------------------------------
className:OF1,classType:OF2,Orign-NameO3,Orign-TypeO4,list-size:3
原型模式是比较简单的设计模式。它没有复杂的多态继承体系之类的,只需要类实现Cloneable接口并重写clone()方法即可。