美文网首页
【设计模式②】建造者、代理、适配器、桥接模式

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

作者: 苡仁ilss | 来源:发表于2019-04-26 16:27 被阅读0次

    建造者模式 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();
        }
    }
    
    参考文章

    相关文章

      网友评论

          本文标题:【设计模式②】建造者、代理、适配器、桥接模式

          本文链接:https://www.haomeiwen.com/subject/nfdqnqtx.html