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、需要过多注释
网友评论