工厂模式
创建对象时不会对客户端暴露创建逻辑,并且通过使用一个共同的接口来指向新创建的对象,实现创建者和调用者分离,工厂模式分为简单工厂、工厂方法、抽象工厂,Spring中的IOC容器创建bean的过程就是用了工厂模式,容器中有个静态的Map集合存储对象,为了让每个对象只生产一次,让工厂符合单例模式。定义一个创建对象的接口,让其子类决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行
优点:
- 工厂模式是最常用的实例化对象模式,工厂方法代替new操作的一种模式
- 降低程序的耦合性
- 将选择实现类、创建对象统一管理控制,将调用者和实现类解耦
简单工厂模式(静态工厂)
相当于一个工厂中有各种产品,客户无需知道产品名称,只需要知道产品类对应的参数,但是工厂的职责过重,而且类型过多时,不利于系统扩展维护,实质是工厂类根据传入的参数动态决定创建哪一个产品类(这些产品类继承一个父类,或实现一个接口)
package com.clay.factory;
public interface Phone {
void run();
}
//产品类 都是实现一个接口
package com.clay.factory;
public class Honor implements Phone{
@Override
public void run() {
System.out.println("Honor");
}
}
package com.clay.factory;
public class Oppo implements Phone{
@Override
public void run() {
System.out.println("OPPO");
}
}
package com.clay.factory;
public class Vivo implements Phone{
@Override
public void run() {
System.out.println("VIVO");
}
}
// 静态工厂类
package com.clay.factory;
public class PhoneFactory {
public static Phone create(String type){
if(type == null){
return null;
}
if(type.equals("Vivo")){
return new Vivo();
}else if(type.equals("Honor")){
return new Honor();
}else if(type.equals("Oppo")){
return new Oppo();
}
return null;
}
}
// 测试
package com.clay.factory;
public class PhoneTest {
public static void main(String[] args) {
Phone vivo = PhoneFactory.create("Vivo");
Phone honor = PhoneFactory.create("Honor");
Phone oppo = PhoneFactory.create("Oppo");
vivo.run();
honor.run();
oppo.run();
}
}
工厂方法模式
此模式的核心是封装类中变化大部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和后期维护扩展的目的。
又称为**多态性工厂模式,工厂类不再负责所有产品的创建,而是具体的创建交给子类去做。**该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
// 产品类和工厂类依然是简单工厂的示例代码
// 工厂方法调用接口
public interface PhoneFactory {
Phone create();
}
// 创建工厂方法调用接口的实例
public class OppoFactory implements PhoneFactory{
@Override
public Phone create() {
return new Oppo();
}
}
public class HonorFactory implements PhoneFactory{
@Override
public Phone create() {
return new Honor();
}
}
public class VivoFactory implements PhoneFactory{
@Override
public Phone create() {
return new Vivo();
}
}
//测试
public static void main(String[] args) {
Phone vivo = new VivoFactory().create();
Phone oppo = new OppoFactory().create();
Phone honor = new HonorFactory().create();
vivo.run();
oppo.run();
honor.run();
}
抽象工厂模式
抽象工厂是工厂的工厂,抽象工厂可以具体创建工厂,由具体工厂来创建具体产品
package com.clay.factory.abstractfac;
// 手机工厂
public interface PhoneFactory {
Camera createCamera(String type);
Screen createScreen(String type);
}
// 摄像头工厂
class CameraFactory implements PhoneFactory{
@Override
public Camera createCamera(String type) {
if(type.equals("CameraA")){
return new CameraA();
}else if(type.equals("CameraB")){
return new CameraB();
}
return null;
}
@Override
public Screen createScreen(String type) {
return null;
}
}
// 屏幕工厂
class ScreenFactory implements PhoneFactory{
@Override
public Camera createCamera(String type) {
return null;
}
@Override
public Screen createScreen(String type) {
if(type.equals("ScreenA")){
return new ScreenA();
}else if(type.equals("ScreenB")){
return new ScreenB();
}
return null;
}
}
// 选择工厂
class PhoneCreateFactory{
public static PhoneFactory getFactory(String factory){
if(factory.equals("Camera")){
return new CameraFactory();
}else if(factory.equals("Screen")){
return new ScreenFactory();
}
return null;
}
}
代理模式
**为其他对象提供一种代理以控制对这个对象的访问。**代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标之间起到中介的作用。代理再原有代码乃至原业务不变的情况下,直接再业务流程中切入新代码。应用场景Spring AOP、日志打印、异常处理等
分类
静态代理:静态代理模式
动态代理(jdk):使用反射完成代理,不能直接代理类,需要有顶层接口才能使用,常见是Mybatis的mapper文件代理。
静态代理
程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了,通常代理类和委托类会实现同一接口或者派生自相同父类
public interface Subject {
void request();
}
// 真实主题
public class RealSubject implements Subject{
@Override
public void request() {
System.out.println("访问真实的主题");
}
}
// 代理 ,一般代理会被理解为代码增强,实际上就是在原代码逻辑前后增加一些代码逻辑,而使调用者无感知。
public class Proxy implements Subject{
private RealSubject realSubject;
@Override
public void request() {
if(realSubject == null){
realSubject = new RealSubject();
}
preRequest();
realSubject.request();
postRequest();
}
public void preRequest(){
System.out.println("访问真实主题之前的操作");
}
public void postRequest(){
System.out.println("访问真实主题之后的操作");
}
}
缺点是每个需要代理的对象都要自己重复编写代理,如果被代理类增加了方法,代理类就要同步增加,不符合开闭原则。
动态代理
使用反射动态创建,利用JDK的API动态的在内存中构建代理对象,能在代码运行时动态改变某个对象的代理,并且能为代理对象动态增加方法,增加行为。必须是面向接口的,目标业务类要实现接口。
public interface Subject {
void request();
}
public class RealSubject implements Subject{
@Override
public void request() {
System.out.println("访问真实的主题");
}
}
public class InvocationHandlerImpl implements InvocationHandler {
private Object target;
public InvocationHandlerImpl(Object target){
this.target = target;
}
// 动态代理实际运行的代理方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用之前处理");
// 反射创建对象,args是构成方法的参数
Object invoke = method.invoke(target, args);
System.out.println("调用之后处理");
return invoke;
}
}
public class Test {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(realSubject);
// 获取类加载器
ClassLoader classLoader = realSubject.getClass().getClassLoader();
// 获取接口
Class<?>[] interfaces = realSubject.getClass().getInterfaces();
Subject subject =(Subject) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
subject.request();
}
}
参考
菜鸟教程(https://www.runoob.com/design-pattern/singleton-pattern.html)
博客https://blog.csdn.net/weixin_43122090/article/details/105462226