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

2020-07-04  本文已影响0人  陈桐Caliburn

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、需要过多注释

上一篇 下一篇

猜你喜欢

热点阅读