设计模式-工厂模式/代理模式

工厂模式

创建对象时不会对客户端暴露创建逻辑,并且通过使用一个共同的接口来指向新创建的对象,实现创建者和调用者分离,工厂模式分为简单工厂、工厂方法、抽象工厂,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值