美文网首页
设计模式的基本概念与区别

设计模式的基本概念与区别

作者: 陈桐Caliburn | 来源:发表于2020-07-04 15:51 被阅读0次

    1、设计模式有哪些?

    23种设计模式
    总体分为三大类
    创建型设计模式,共5种
    简单工厂、工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式

    结构型模式,共7种
    适配器模式,装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式

    行为型模式,共11种
    策略模式,模板方法,观察者模式,迭代模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式

    2、设计模式定义

    1、 设计模式按照类型划分

    • 创建型设计模式:用来解耦对象的实例化过程。
    • 结构型设计模式:将类和对象按照一定规则组合成一个更加强大的结构体。
    • 行为型设计模式:定义类和对象的交互行为。

    2、 设计模式简单定义


    23种设计模式简单定义

    3、文字版
    1)创建型设计模式

    • 单例模式:确保一个类只有一个实例,提供一个全局访问点
    • 建造者模式:封装一个复杂对象过程,按照步骤构建对象
    • 原型模式:通过复制现有实例创建新实例
    • 简单工厂模式:一个工厂类根据传入参数决定创建哪一种产品实例
    • 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化那个类
    • 抽象工厂模式:创建相关依赖对象家族,而无须指定具体类

    2)结构型设计模式

    • 适配器模式:将一个类的方法或者接口转换成客户希望另一个接口
    • 组合模式:将对象组成成树形结构以表示“整体-部分”的层次结构
    • 装饰模式:动态的给对象添加新的功能
    • 外观模式:对外提供一个统一方法,用来访问子系统中一群接口
    • 桥接模式:将抽象部分与实现部分分离,使他们都可以独立进行变化
    • 享元模式:通过共享技术来有效支持大量细粒度的对象
    • 代理模式:为其他对象提供一种代理以控制对这个对象的访问

    3)行为型设计模式

    • 模板模式:定义一个算法结构,而将一些步骤延迟到子类实现
    • 解释器模式:定义一个语言,定义它的文法的一种表示,并定义一个解释器
    • 策略模式:定义一系列算法,把它们封装起来,并且使它们可以互相替换
    • 状态模式:允许一个对象在其内部状态改变时改变它的行为
    • 观察者模式:对象间一对多依赖关系,一个对象改变,依赖于它对象得到通知并更新
    • 备忘录模式:在不破坏封装前提下,保存对象内部状态
    • 中介者模式:用一个中介对象来封装一系列对象交互
    • 命令模式:将命令请求封装成一个对象,可以将不同请求来进行参数化
    • 访问者模式:在不改变数据结构的前提下,增加作用于一组元素对象新功能
    • 责任链模式:将请求的发送者和接受者解耦,使得多个对象都有处理这个请求的机会
    • 迭代器模式:一种遍历访问容器对象中各个元素的方法,不暴露该对象内部结构
    3、动态代理和静态代理区别

    区别在于代理类生成时间不同,根据程序运行时代理类是否存在

    应用场景:retrofit使用动态代理提升扩展性

    4、动态代理写法

    参考 https://github.com/yinlingchaoliu/23-design-pattern.git

    公共部分

    //接口
    public interface ILawsuit {
    
        //提交申请
        void submit();
    
        //举证
        void burden();
    
        //辩护
        void defend();
    
        //诉讼完成
        void finish();
    
    }
    
    public class XiaoMin implements ILawsuit {
    
        @Override
        public void submit() {
            //小民申请仲裁
            System.out.println( "老板年底拖欠工资,特此申请仲裁!" );
        }
    
        @Override
        public void burden() {
            //小民提交证据
            System.out.println( "这是合同书和过去一年的银行工资流水!" );
        }
    
        @Override
        public void defend() {
            //铁证如山
            System.out.println( "证据确凿,不需要再说什么!" );
        }
    
        @Override
        public void finish() {
            //结果
            System.out.println( "诉讼成功,判决老板即日起七天内结算工资!" );
        }
    
    }
    

    静态代理

    /**
     * 代理类
     */
    public class Lawyer implements ILawsuit {
    
        private ILawsuit mLawsuit;
    
        public Lawyer(ILawsuit mLawsuit) {
            this.mLawsuit = mLawsuit;
        }
    
        @Override
        public void submit() {
            mLawsuit.submit();
        }
    
        @Override
        public void burden() {
            mLawsuit.burden();
        }
    
        @Override
        public void defend() {
            mLawsuit.defend();
        }
    
        @Override
        public void finish() {
            mLawsuit.finish();
        }
    }
    
    测试类
    public class TestMain {
    
        public static void main(String[] args) {
            ILawsuit xiaomin = new XiaoMin();
            //静态代理
            ILawsuit lawyer = new Lawyer( xiaomin );
            lawyer.submit();
            lawyer.burden();
            lawyer.defend();
            lawyer.finish();
        }
    }
    

    动态代理 第一种写法

    /**
     *
     * 动态代理
     *
     */
    public class DynamicProxy implements InvocationHandler {
    
        private Object obj;
    
        public DynamicProxy(Object obj) {
            this.obj = obj;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = method.invoke( obj,args );
            return result;
        }
    }
    
    
    public class TestMain {
    
        public static void main(String[] args) {
            ILawsuit xiaomin = new XiaoMin();
            //动态代理
            DynamicProxy proxy = new DynamicProxy( xiaomin );
            //获取小民的classLoader
            ClassLoader loader = xiaomin.getClass().getClassLoader();
            //动态代理一个代理律师
            ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance( loader, new Class[]{ILawsuit.class}, proxy );
            lawyer.submit();
            lawyer.burden();
            lawyer.defend();
            lawyer.finish();
        }
    
    }
    

    动态代理第二种通用式写法

    
    public class DynamicProxy {
    
       //需要特别指定泛型类
        public static <T> T create(Class<T> serivce, final Object newInstance) {
            InvocationHandler proxy = new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return method.invoke( newInstance, args );
                }
            };
            ClassLoader loader = serivce.getClassLoader();
            return (T) Proxy.newProxyInstance( loader, new Class[]{serivce}, proxy );
        }
    }
    
        /**
         * 需要那个接口 泛型指向那个
         * T必须为接口类
         * @param newInstance
         * @param <T>
         * @return
         */
        public static <T> T create(final Object newInstance) {
    
            InvocationHandler proxy = new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return method.invoke( newInstance, args );
                }
            };
    
            //获得接口列表
            Class[] ifaces = newInstance.getClass().getInterfaces();
            //获取实体类classLoader
            ClassLoader loader = newInstance.getClass().getClassLoader();
            //获得动态代理实例
            return (T) Proxy.newProxyInstance( loader, ifaces, proxy );
        }
    
        //retrofit写法
        /**
         * 没有真正实体类
         * 可以用invoke方法反射
         * @param service
         * @param <T>
         * @return
         */
        public static <T> T create(Class<T> service) {
            ClassLoader loader = service.getClassLoader();
    
            InvocationHandler proxy = new InvocationHandler() {
    
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //这里填写回调,没有newInstance retrofit用法
                    return null;
                }
            };
            return (T) Proxy.newProxyInstance( loader, new Class[]{service}, proxy );
        }
    }
    

    测试类

        public static void main(String args[]){
    
            //第一种方式:指定接口
            ILawsuit lawsuit =  DynamicProxy.create( ILawsuit.class, new XiaoMin() );
            lawsuit.submit();
            lawsuit.burden();
    
            //第二种方式:采用接口转换
            ILawsuit mlawsuit =  DynamicProxy.create(  new XiaoMin() );
            mlawsuit.defend();
    
            IArgue argue =  DynamicProxy.create(  new XiaoMin() );
            argue.argue();
    
            //转换时 必须用接口才行
            ILawsuit judge = (ILawsuit)argue;
    
            judge.finish();
        }
    
    5、简单工厂、工厂方法、抽象工厂、建造者模式区别

    简单工厂:一个工厂方法创建不同类型对象
    工厂方法:一个具体工厂类负责创建一个具体对象类型
    抽象工厂:一个具体工厂类负责创建一系列相关对象
    建造者模式:对象的构建与表现分离,更注重对象创建过程

    6、装饰模式与代理模式区别、与桥接者模式相比

    1、装饰模式以客户端透明方式扩展对象的功能,是继承关系替代方案。
    代理模式是给一个对象提供代理对象,并由代理对象来控制原有对象引用
    2、装饰模式应该为所装饰对象增强功能,代理模式对所代理对象施加控制,但不对对象功能本身增加
    3、桥接模式主要为应对某个类多个变化维度增加场景,通过桥接把多个变化隔离开

    7、外观模式和中介模式区别

    外观模式重点对外封装统一高层接口,便于用户使用。
    中介模式避免多个互相协作对象直接易用。他们之间通过一个中介对象进行,从而得到他们耦合松散,易于应对变化

    8、策略模式和状态模式区别

    类型结构一致,本质不同,策略模式重在整个算法的替换,也就是策略替换,而状态模式则是通过状态来改变行为

    9、适配器模式、装饰者模式、外观模式异同

    相同之处,在用户类与被调用类之间加了一个中间层
    不同之处
    代理对象表示一个单一对象
    外观对象表示一个子系统
    适配器和外观是对现存系统封装
    外观定义新接口,简化接口
    适配器则是复用原有接口,侧重于接口转换

    10、重构之代码坏味道

    记住坏味道,在文集《重构 改善代码设计》-代码坏味道中
    记住一个原则:事不过三,三则重构
    常见坏味道要点:
    1、代码重复
    2、方法过长
    3、类功能过多
    4、过长参数列表
    5、冗余类
    6、需要过多注释

    相关文章

      网友评论

          本文标题:设计模式的基本概念与区别

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