1995 年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。这 23 种设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性,以及类的关联关系和组合关系的充分理解。
设计模式分三大类(共23种):
- 创建型模式:1.单例模式、2.工厂方法模式、3.抽象工厂模式、4.建造者模式、5.原型模式。共5种
- 结构型模式:6.适配器模式、7.装饰器模式、8.代理模式、9.桥接模式、10.外观模式、11.组合模式、12.享元模式。共7种
- 行为型模式:13.观察者模式、14.访问者模式、15.中介者模式、16.解释器模式、17.策略模式、18.模板方法模式、19.迭代子模式、20.责任链模式、21.命令模式、22.备忘录模式、23状态模式。共11种
一.创建型模式
1.单例模式
单例(Singleton)模式:指一个类只有一个实例,且该类能自行创建这个实例的一种模式
应用:Spring 中的 Bean 默认都是单例的
/** * ClassName:EnumSingleton * Description:枚举单例模式 * Author:YMJ * Date:2020-07-10 23:24 * Version:V1.0 */ public class EnumSingleton { //私有构造函数防止外部实例化 private EnumSingleton(){} static enum enumClass{ //创建一个枚举对象(天生为单例) INSTANCE; private EnumSingleton enumSingleton; //私有枚举构造函数防止外部实例化 private enumClass(){ enumSingleton = new EnumSingleton(); } public EnumSingleton getInstance(){ return enumSingleton; } } public EnumSingleton getInstance(){ return enumClass.INSTANCE.getInstance(); } //特点:防止反射攻击和反序列化攻击 缺点:写法略微复杂 }
2.工厂方法模式
工厂方法(FactoryMethod)模式:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
- 创建抽象产品
- 创建抽象工厂
- 创建具体产品
- 创建具体产品工厂
/** * ClassName:FactoryMethodPattern * Description:工厂方法模式 * Author:YMJ * Date:2020-07-19 22:33 * Version:V1.0 */ public class FactoryMethodPattern { public interface Product{ public void show(); } public interface MyFactory{ public Product creatProduct(); } public static class Product_A implements Product{ @Override public void show() { System.out.println("生产了一件A产品"); } } public static class MyFactory_A implements MyFactory{ @Override public Product creatProduct() { return new Product_A(); } } public static class Product_B implements Product{ @Override public void show() { System.out.println("生产了一件B产品"); } } public static class MyFactory_B implements MyFactory{ @Override public Product creatProduct() { return new Product_B(); } } public static void main(String[] args) { MyFactory myFactory; myFactory = new MyFactory_A(); myFactory.creatProduct().show(); myFactory = new MyFactory_B(); myFactory.creatProduct().show(); } // 输出结果 缺点:只能创建一类产品,本例中只能创建Product类产品 // 生产了一件A产品 // 生产了一件B产品 }
缺点:只能生产一类产品,且一类产品中每增加一个产品都要增加相应工厂类
3.抽象工厂模式
抽象工厂(AbstractFactory)模式:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
- 创建多种类抽象产品
- 创建抽象工厂
- 创建具体种类产品
- 创建具体工厂
/** * ClassName:AbstractFactoryPattern * Description:抽象工厂模式 * Author:YMJ * Date:2020-07-19 23:17 * Version:V1.0 */ public class AbstractFactoryPattern { //创建多种抽象产品 public interface AbstractProductTypeA{ public void show(); } public interface AbstractProductTypeB{ public void call(); } //创建抽象工厂 public interface AbstractFactory{ public AbstractProductTypeA creatProductTypeA(); public AbstractProductTypeB creatProductTypeB(); } //创建具体产品 public static class ProductTypeA implements AbstractProductTypeA{ @Override public void show() { System.out.println("创建了A类产品一件"); } } public static class ProductTypeB implements AbstractProductTypeB{ @Override public void call() { System.out.println("创建了B类产品一件"); } } public static class MyFacory implements AbstractFactory{ @Override public AbstractProductTypeA creatProductTypeA() { return new ProductTypeA(); } @Override public AbstractProductTypeB creatProductTypeB() { return new ProductTypeB(); } } public static void main(String[] args) { AbstractFactory factory = new MyFacory(); factory.creatProductTypeA().show(); factory.creatProductTypeB().call(); } //输出结果: //创建了A类产品一件 //创建了B类产品一件 }
优点:能生产各类产品,且只用一个工厂类管理
4.建造者模式
建造者(Builder)模式:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
- 创建产品类:包含产品各个组件属性以及产品展示方法
- 创建抽象建造者:包含建造产品各个组件的抽象方法
- 创建实际建造者:通过继承抽象建造者实现各个组件的建造过程
- 创建指挥者:通过指挥实际建造者建造产品各个部分并组装成完整产品
/** * ClassName:BuilderPattern * Description:建造者模式 * Author:YMJ * Date:2020-07-20 20:06 * Version:V1.0 */ public class BuilderPattern { //产品类:包含各个组成部分的复杂对象 public static class Product{ private String partA; private String partB; private String partC; public void setPartA(String partA) { this.partA = partA; } public void setPartB(String partB) { this.partB = partB; } public void setPartC(String partC) { this.partC = partC; } public void show(){ System.out.println("产品建造完毕,各部件分别是:" + partA + ";" + partB + ";" + partC); } } //抽象建造者:包含创建产品的各个子部件的抽象方法 public static abstract class AbstractBuilder{ private Product product = new Product(); //定义建造部件A的抽象方法 public abstract void buildPartA(); //定义建造部件B的抽象方法 public abstract void buildPartB(); //定义建造部件C的抽象方法 public abstract void buildPartC(); //返回产品对象 public Product getProduct(){ return product; } } //具体建造者:继承抽象建造者,实现每个部件具体建造过程 public static class RealBuilder extends AbstractBuilder{ @Override public void buildPartA() { getProduct().setPartA("A部件"); } @Override public void buildPartB() { getProduct().setPartB("B部件"); } @Override public void buildPartC() { getProduct().setPartC("C部件"); } } //指挥者:调用建造者中的方法完成复杂对象的创建 public static class Director{ private AbstractBuilder abstractBuilder; public Director(AbstractBuilder abstractBuilder){ this.abstractBuilder = abstractBuilder; } //提供产品的构建与组装方法 public Product build(){ abstractBuilder.buildPartA(); abstractBuilder.buildPartB(); abstractBuilder.buildPartC(); return abstractBuilder.getProduct(); } } //客户端 public static void main(String[] args) { AbstractBuilder builder = new RealBuilder(); Director director = new Director(builder); Product product = director.build(); product.show(); } }
建造者模式相比工厂模式更注重于产品的组装过程;工厂模式更注重于产品部件的创建过程
5.原型模式
原型(Prototype)模式:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象,这就是克隆clone。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。clone方法是native方法,比new一个快得多。clone分为浅克隆与深克隆。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
/** * ClassName:PrototypePattern * Description:原型模式,模板模式 * Author:YMJ * Date:2020-07-20 20:57 * Version:V1.0 */ public class PrototypePattern { public static class MyObject implements Cloneable{ public String objectName; public MyObject() { this.objectName = "MyObject"; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "MyObject{" + "objectName='" + objectName + '\'' + ',' + this.hashCode() + '}'; } } public static class PrototypeObject implements Cloneable{ public String prototypeObjectName; public MyObject myObject = new MyObject(); public PrototypeObject() { prototypeObjectName = "MyPrototypeObject"; System.out.println("原型对象创建成功"); } public void setMyObject(MyObject myObject) { this.myObject = myObject; } public MyObject getMyObject() { return myObject; } @Override public String toString() { return "PrototypeObject{" + "prototypeObjectName='" + prototypeObjectName + '\'' + ", myObject=" + myObject.toString() + '}'; } @Override protected Object clone() throws CloneNotSupportedException { System.out.println("原型对象浅克隆成功"); return super.clone(); } // @Override // protected Object clone() throws CloneNotSupportedException { // System.out.println("原型对象深克隆成功"); // PrototypeObject prototypeObject = (PrototypeObject) super.clone(); // prototypeObject.setMyObject((MyObject) prototypeObject.getMyObject().clone()); // return prototypeObject; // } } public static void main(String[] args) { PrototypeObject prototypeObject = new PrototypeObject(); System.out.println(prototypeObject.toString()); try { PrototypeObject cloneObject = (PrototypeObject) prototypeObject.clone(); System.out.println(cloneObject.toString()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
浅克隆输出:
原型对象创建成功 PrototypeObject{prototypeObjectName='MyPrototypeObject', myObject=MyObject{objectName='MyObject',460141958}} 原型对象浅克隆成功 PrototypeObject{prototypeObjectName='MyPrototypeObject', myObject=MyObject{objectName='MyObject',460141958}}
深克隆输出:
原型对象创建成功 PrototypeObject{prototypeObjectName='MyPrototypeObject', myObject=MyObject{objectName='MyObject',460141958}} 原型对象深克隆成功 PrototypeObject{prototypeObjectName='MyPrototypeObject', myObject=MyObject{objectName='MyObject',1163157884}}
从输出结果就能看出,浅克隆对于克隆对象中的引用类型,克隆后引用地址仍不变,而深克隆克隆后对象中的引用类型地址发生了变化