设计模式—【02】建造者、代理、适配器、桥接模式

建造者模式 Builder

定义

  • 建造者模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
  • 建造者(Builder)模式的角色:
  1. 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个滅部件。
  2. 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
  3. 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  4. 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
    在这里插入图片描述

以制造自行车为例,自行车由车架、轮胎、脚踏等部件组成,自行车制造公司就是把这些零部件组装起来。

自行车制造公司的工程部门相当于指挥者,生产部门相当于建造者,当今共享单车做的比较大的摩拜和ofo相当于客户,单车就是产品了。结构图如下所示:
在这里插入图片描述

实现

package io.ilss.pattern.builder;

import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: Product
 * @date : 2019-04-23 15:14
 * @version: : 1.0
 */
@Setter
@Slf4j
@ToString
class Product {
    private String partA;
    private String partB;
    private String partC;

    public void show() {
        log.info(toString());
    }
}
package io.ilss.pattern.builder;

/**
 * @author : feng
 * @description: Builder 抽象产品建造者
 * @date : 2019-04-23 15:19
 * @version: : 1.0
 */
public abstract class Builder {
    //创建产品对象
    protected Product product = new Product();

    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    //返回产品对象
    public Product getResult() {
        return product;
    }
}
package io.ilss.pattern.builder;

/**
 * @author : feng
 * @description: ConcreteOneBuilder 具体的建造者
 * @date : 2019-04-23 15:20
 * @version: : 1.0
 */
public class ConcreteOneBuilder extends Builder {

    @Override
    public void buildPartA() {
        product.setPartA("PartA-1");
    }

    @Override
    public void buildPartB() {
        product.setPartB("PartB-1");
    }

    @Override
    public void buildPartC() {
        product.setPartC("PartC-1");
    }
}
package io.ilss.pattern.builder;

/**
 * @author : feng
 * @description: ConcreteTwoBuilder
 * @date : 2019-04-23 15:22
 * @version: : 1.0
 */
public class ConcreteTwoBuilder extends Builder{

    @Override
    public void buildPartA() {
        product.setPartA("PartA-2");
    }

    @Override
    public void buildPartB() {
        product.setPartB("PartB-2");
    }

    @Override
    public void buildPartC() {
        product.setPartC("PartC-2");
    }
}
package io.ilss.pattern.builder;

/**
 * @author : feng
 * @description: Director
 * @date : 2019-04-23 15:21
 * @version: : 1.0
 */
public class Director {
    private Builder builder;
    public Director(Builder builder)
    {
        this.builder=builder;
    }
    //产品构建与组装方法
    public Product construct()
    {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}

代理模式 Proxy

定义

  • 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

  • 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是生活中常见的中介。

  • 代理模式包含一下三个角色:

  1. 抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  2. 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  3. 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
    在这里插入图片描述

实现

  • 代理模式实现
package io.ilss.pattern.proxy;

/**
 * @author : feng
 * @description: Subject 抽象主题
 * @date : 2019-04-24 09:16
 * @version: : 1.0
 */
public interface Subject {
    void request();
}
package io.ilss.pattern.proxy;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: RealSubject 真实主题
 * @date : 2019-04-24 09:17
 * @version: : 1.0
 */
@Slf4j
public class RealSubject implements Subject {
    @Override
    public void request() {
        log.info("访问真实主题方法...");
    }
}
package io.ilss.pattern.proxy;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: Proxy 代理
 * @date : 2019-04-24 09:16
 * @version: : 1.0
 */
@Slf4j
class Proxy implements Subject {
    private Subject subject;

    @Override
    public void request() {
        if (subject == null) {
            subject = new RealSubject();
        }
        log.info("访问真实主题之前的预处理。");
        subject.request();
        log.info("访问真实主题之后的后续处理。");
    }
}
package io.ilss.pattern.proxy;

/**
 * @author : feng
 * @description: ProxyTest
 * @date : 2019-04-24 09:19
 * @version: : 1.0
 */
public class ProxyTest {
    public static void main(String[] args) {
        Proxy proxy=new Proxy();
        proxy.request();
    }
}

  • jdk动态代理简单实现
package io.ilss.pattern.proxy.jdk;

/**
 * @author : feng
 * @description: Work
 * @date : 2019-04-24 09:22
 * @version: : 1.0
 */
public interface Work {
    void todo();
}
package io.ilss.pattern.proxy.jdk;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: Work
 * @date : 2019-04-24 09:23
 * @version: : 1.0
 */
@Slf4j
public class WorkImpl implements Work {
    
    @Override
    public void todo() {
        log.info("do some work jdk!");
    }
}
package io.ilss.pattern.proxy.jdk;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author : feng
 * @description: JdkProxy
 * @date : 2019-04-24 09:26
 * @version: : 1.0
 */
@Slf4j
public class JdkProxy implements InvocationHandler {
    private Object object;

    public JdkProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("开始预处理");
        object = method.invoke(object, args);
        log.info("结结束时处理");
        return object;
    }

    public Object getInstance() {
        return Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), new Class[]{Work.class}, this);
    }
}
package io.ilss.pattern.proxy.jdk;

import java.lang.reflect.Proxy;

/**
 * @author : feng
 * @description: ProxyTest
 * @date : 2019-04-24 09:33
 * @version: : 1.0
 */
public class ProxyTest {
    public static void main(String[] args) {
        JdkProxy proxy = new JdkProxy(new WorkImpl());
        Work work = (Work) proxy.getInstance();
        work.todo();
    }
}
  • cglib 动态代理简单实现
package io.ilss.pattern.proxy.cglib;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: Work
 * @date : 2019-04-24 09:23
 * @version: : 1.0
 */
@Slf4j
public class Work {

    public void todo() {
        log.info("do some work cglib!");
    }
}
package io.ilss.pattern.proxy.cglib;

import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author : feng
 * @description: CglibProxy
 * @date : 2019-04-25 10:17
 * @version: : 1.0
 */
@Slf4j
public class CglibProxy implements MethodInterceptor {

    private Object object;

    public CglibProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        log.info("开始预处理");
        object = methodProxy.invokeSuper(o, objects);
        log.info("结结束时处理");
        return object;
    }

    public Object getInstance() {
        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer();
        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(this.object.getClass());
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }
}
package io.ilss.pattern.proxy.cglib;

/**
 * @author : feng
 * @description: ProxyTest
 * @date : 2019-04-24 09:33
 * @version: : 1.0
 */
public class ProxyTest {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy(new Work());
        Work work = (Work) proxy.getInstance();
        work.todo();
    }
}

适配器模式 Adapter

定义

将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作

  • 类适配器
    在这里插入图片描述
  • 对象适配器
    在这里插入图片描述
    适配器模式包含一下三个角色:
  1. Target(目标抽象类):目标抽象类定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类。在类适配器中,由于C#语言不支持多重继承,所以它只能是接口。
  2. Adapter(适配器类):它可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配。它是适配器模式的核心。
  3. Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类包好了客户希望的业务方法。

实现

package io.ilss.pattern.adapter;

/**
 * @author : feng
 * @description: Target 目标接口
 * @date : 2019-04-25 14:26
 * @version: : 1.0
 */
interface Target {
    public void request();
}
package io.ilss.pattern.adapter;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: Adaptee 适配者接口
 * @date : 2019-04-25 14:27
 * @version: : 1.0
 */
@Slf4j
public class Adaptee {
    public void specificRequest() {
        log.info("适配者中的业务代码被调用!");
    }
}
  • 类适配器
package io.ilss.pattern.adapter;

/**
 * @author : feng
 * @description: ClassAdapter 类适配器类
 * @date : 2019-04-25 14:27
 * @version: : 1.0
 */
public class ClassAdapter extends Adaptee implements Target {

    @Override
    public void request() {
        specificRequest();
    }
}
  • 对象适配器
package io.ilss.pattern.adapter;

/**
 * @author : feng
 * @description: ObjectAdapter 对象适配器
 * @date : 2019-04-25 14:28
 * @version: : 1.0
 */
public class ObjectAdapter implements Target {

    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}
package io.ilss.pattern.adapter;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: AdapterTest
 * @date : 2019-04-25 14:29
 * @version: : 1.0
 */
@Slf4j
public class AdapterTest {
    public static void main(String[] args) {
        log.info("类适配器模式:");
        Target target1 = new ClassAdapter();
        target1.request();

        log.info("对象适配器模式测试:");
        Adaptee adaptee = new Adaptee();
        Target target2 = new ObjectAdapter(adaptee);
        target2.request();
    }
}

桥接模式 Bridge

定义

  • Bridge 模式是构造型的设计模式之一。Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。
  • Bridge将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
  • 桥接(Bridge)模式包含以下主要角色。
  1. 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
  2. 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现3. 父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  3. 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
  4. 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
    在这里插入图片描述

实现

package io.ilss.pattern.bridge;

/**
 * @author : feng
 * @description: Implementor 实现化角色
 * @date : 2019-04-26 16:00
 * @version: : 1.0
 */
public interface Implementor {
    void operationImpl();
}
package io.ilss.pattern.bridge;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: ConcreteImplementorA
 * @date : 2019-04-26 16:01
 * @version: : 1.0
 */
@Slf4j
public class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        log.info("具体实现化(Concrete Implementor)角色被访问 ConcreteImplementorB!!!");
    }
}
package io.ilss.pattern.bridge;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: ConcreteImplementorB
 * @date : 2019-04-26 16:08
 * @version: : 1.0
 */
@Slf4j
public class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        log.info("具体实现化(Concrete Implementor)角色被访问 ConcreteImplementorB!!!");
    }
}
package io.ilss.pattern.bridge;

/**
 * @author : feng
 * @description: Abstraction
 * @date : 2019-04-26 16:03
 * @version: : 1.0
 */
public abstract class Abstraction {
    protected Implementor implementor;

    protected Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    public abstract void operation();
}
package io.ilss.pattern.bridge;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : feng
 * @description: RefineAbstraction
 * @date : 2019-04-26 16:04
 * @version: : 1.0
 */
@Slf4j
public class RefinedAbstraction extends Abstraction {
    protected RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    public void operation() {
        log.info("扩展抽象化(Refined Abstraction)角色被访问");
        implementor.operationImpl();
    }
}
参考文章
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值