类的创建模式:使用继承关系,把类的创建延迟到子类
对象的创建模式:对象的创建过程动态地委派给另一个对象
i. 对于两个构造函数,如果参数类型和个数相同,则只能使用不同的顺序进行区分,而使用工厂函数可以为这两个构造函数指明不同的名称
ii. 如果有多个构造函数,可考虑用静态工厂方法替换
i. 当系统需要该类的N或1个实例,如果使用构造函数,则每次调用都会创建一个实例,可通过单例或多例模式重用已有实例
i. 对于一个继承体系,在基类中声明静态工厂方法,根据type返回不同的子类实例,且该子类为package 或 private,可以向客户端隐藏子类。
具体原因参考 effective java
由一个工厂类决定创建出哪一种产品的实例,对客户端隐藏具体子类的实例化
用于 产品类结构层次简单,修改不频繁
IProduct:作为产品接口
ProductA 和ProductB 作为具体的产品
SimpleFactory 使用方法 static IProduct createProduct(String type) 根据type创建产品,可以有多个create方法
Client:使用产品 IProduct
1. 创建产品的责任从客户端移交给了工厂类,客户端仅使用;
2. 增加新的产品需要修改工厂类,容易变成fatmethod;产品类的等级结构不能反应到工厂类中;静态方法无法被继承
简单工厂可以和抽象产品类合并,根据type,返回具体的子类,实例如 DateFormat.getTimeInstance();
简单工厂、抽象产品和具体类合并 就快退化成了单例模式
对于非 简单工厂 支持的类型,可以抛出BadTypeException 异常
定义工厂接口 Creator,将具体创建工作放到子类 ConcreteCreator 中
当产品类具有较复杂的结构,如产品树高度大于2,有多个抽象类,则将工厂也按产品类形成类似结构,只有具体工厂类完成产品的创建
Product:框架包内,产品接口,构造函数非公有,规定应有的方法。
Creator:框架包内,生产者接口,定义public Produt create()
ConcreteProduct:实际处理包内,构造函数非公有,具体产品
ConcreteCreator:实际处理包内,实现create方法。
对简单工厂 抽象为 Creator和ConcreteCreator,当加入新的产品,只需要增加工厂和产品类,不需要修改抽象类
支持开闭原则
在client中有Creatortc=new 具体工厂()
Creator中工厂函数返回为抽象产品类 Product
对简单工厂模式的SimpleCreator 执行重构 :replace switch with polysim 后得到工厂模式
和其他模式关系:
工厂模式常和模板模式结合使用:模板模式将某一顶级行为分解为多个创建行为,而具体的创建由子类来实现
享元模式使用了带有循环逻辑的工厂方法
备忘录模式中的多例可以使用工厂方法来创建
java中的Collection 和Iterator 的关系
不必指定产品的类型,就可以创建多个平行的产品族中的产品对象
有多个产品体系,这些产品体系有类似的结构且相互关联,如windows和macOS的显示组件。
解决:具体工厂类创建产品体系间某一类型的具体产品,如使用不同的方法创建不同操作系统的menu。
AbstractProduct:规定抽象零件的接口,有多种类,每种作为不同产品体系的顶层类,如 WindowsUI, LinuxUI 。
AbstractFactory: 接口,定义创建产品族的方法,有几个产品族就有几个方法,每个方法返回某一AbstractProduct。有两个函数 一个创建 WindowUI, 一个创建LinuxUI 对象 简单工厂的静态方法返回具体的工厂
Client:调用AbstractFactory实例,只使用AbstractFactory和AbstractProduct接口
ConcreteProduct:实现了AbstractProduct
ConcreteFactory:实现AbstractFactory中方法,如MenuFactory 实现AbstractFactory,有两个函数 一个创建 WindowUI, 一个创建LinuxUI 对象
有多于一个的产品族(产品族和体系结构可构造二维的相图),系统一次只消费一族的产品
创建不同操作系统中的视图
工厂模式:针对一个产品等级结构,而抽象工厂针对多个平行的产品等级结构;
简单工厂模式:抽象工厂有静态函数返回具体工厂实例:隐藏具体工厂类
单例模式:具体工厂类有静态函数就变成单例模式
桥梁模式:抽象工厂模式为桥梁模式提供某一等级结构的创建
创建在程序中只有一个的对象,如充当计数器的类对象。
单例类因为私有构造函数,不能被继承
单例类可扩展为N例类
单例方便mock,静态类比较麻烦
单例可继承抽象类和实现接口,静态类不行
Singleton:创建单例的类,包含静态函数getInstance(),私有构造函数,本类的对象
单例模式:整个系统只有一个实例
多例模式:有多种实例,但每种实例只有一个
对象创建后直到环境重启一直存在
在使用EJB RMI和JINI系统中 、一个JVM有多个类加载器的情况下不要使用 带状态的单例
最简单的方法:静态成员变量private static Singleton instance = new Singleton(); 这样在类第一次加载时,就会创建单例,如果创建非常消耗资源,而始终没有使用就浪费了,可以使用懒加载改进,但懒加载在多线程环境下会有问题,singleton可能会出现多个实例? 解决的办法很简单,加个同步修饰符:public static synchronized Singleton getInstance(). 这样就保证了线程的安全性,但这样要求每次调用getInstance() 获得单例锁,但其实在创建完以后就没有必要了,解决方案是 double-check (两次判断instance==null,对第二次synchronized ),如下所示:
if(uniqueInstance == null){ synchronized(Singleton.class){ //进入同步区域 if(uniqueInstance == null){ //在检查一次,如果为null,则创建 uniqueInstance = new Singleton(); } } }
但在JVM中执行时,分配内存和创建实例是分开的还会有问题,考虑使用内部类
public class Singleton{ private Singleton(){ … } private static class SingletonContainer{ private static Singleton instance = new Singleton(); } public static Singleton getInstance(){ return SingletonContainer.instance; } }
积木式构造更复杂的对象。
1. 每一个具体的builder都相互独立,可以很方便扩展ConcreteBuilder
2. Client不知道产品内部组成的细节
1. 要构造的对象比较复杂。
2 . 构造对象的属性有顺序(在director中指定构造顺序)
3. 构造中使用到系统中的其他一些对象,而这些对象在new 中不易得到, set传入。
Builder:接口,定义零件建造方法,有两种方法,零件构建 void createPart;获取产品 getProduct.
ConcreteBuilder:实现类,构造具体的零件,提供具体的产品
ConcretePart:构建对象的零件,由ConcreteBuilder新建,只在本类可见
Director:以特定顺序调用Builder方法生产产品, 使用Builder.getProduct获取产品
Client:创建Director和ConcreteBuilder对象,调用direcotr.construct()创建,调用ConcreteBuilder.getProduct获取产品 。
Client 找到Director和ConcreteBuilder要创建产品;Director负责使用零件组装产品,所以需要定义需要零件的类型和个数;ConcreteBuilder根据规格 Builder ,创建需要的零件。
Product将属性的建造外部化到对象Builder和ConcreteBuilder中,并通过Director对这些属性的顺序进行协调。
在实际中,Client中的创建放在springxml中进行,则client只要调用 director.construct() 即可。
有多少类产品,就有多少 ConcreteBuilder,这些类产品有一样数目的零件, 有多少种零件,Builder中就有多少建造方法。
对于多个Product类,其本身可能没有太多的共有方法,但为了客户端方便访问,提供一个标识接口Product,客户端可使用向下转型进行使用
去掉Builder:只有一个具体的构造者时(不建议)
去掉Director: 将construct方法放在Builder中
合并Builder和Product: 如果只有固定的零件时
“谁知道哪个部分”相当重要
Client知道Director和ConcreteBuidler,但不知道具体的构建过程
Director 唯一知道的就是Builder类 ,但并不知道实际利用的是哪个ConcreteBuilder。
抽象工厂:建造模式中的ConcretePart,可通过抽象工厂来得到
策略模式:不同的具体策略类实现效果相同,而不同的ConcreteBuilder 创建的产品完全不一样
合成模式:合成模式描述对象树的组织结构,建造模式描述对象树的生成过程
以一个对象为原型,产生出新的对象实例,实现clonable接口,使用Lang中的clone方法。
是 接口+实现 和 javaClonable 接口的结合
增加新的产品类,对其他内容无影响
缺点是对每个类都要配备clone方法,如果该类引用了不支持Seariable对象,或者含有循环结构就麻烦了
Prototype:要复制对象的接口,继承了Clonable接口(或者直接就是CLoneable接口)
ConcretePrototype:实现接口,clone() 完成对象的拷贝
Client: 使用Prototype.clone()完成对象的赋值
调用java 对象clone方法,需要该对象实现Clonable 接口,建议同时实现equals(默认比较引用) 方法
深拷贝的实现:对象实现Seriable接口,将对象写到流中,然后再从流中读出
工厂模式:原型模式创建对象时,和对象的产品结构无关
合成模式:经常一起使用,合成对象也是原型对象
门面模式:原型模式的客户端可以起到门面对象的作用
装饰模式:串行化用到的IO 中使用了装饰模式