目录
-
单例设计模式
-
懒汉模式
- 线程安全问题
- 双重检查,枷锁优化
- 编译器(JIT),CPU有可能对指令进行从新排序,导致尚未实例化就返回对象,导致获取空数据,可加volatile关键字,防止指令重排序
-
public class Single_3 { public static volatile Single_3 single_3; public static Single_3 getInstance(){ synchronized (Single_3.class){ if (single_3 != null){ single_3 = new Single_3(); } } return Single_3.single_3; } }
-
饿汉模式
- 类加载的时候完成实例的初始化,本质上借助jvm的类加载机制,保证实例的唯一性
- 类加载的过程
- 加载二进制数据到内存中,生成对应的class数据结构
- 连接
- 初始化,给类的静态变量赋值
- 饿汉式可反射多次实例化
-
public class Single_2 { public static Single_2 single_2 = new Single_2(); public Single_2(){} public Single_2 getInstance(){ return single_2; } }
-
静态内部类(推荐使用)
- 本质上利用类加载机制保证线程安全
- 只有在实际使用,才会触发类的初始化,也是懒加载的一种
- 和饿汉模式的区别,都是在类加载机制保证线程安全的另一种模式,另一种懒汉模式
- 静态内部类可反射多次实例化
-
public class Single_4 { public Single_4(){ if (SingleHolder.single_4 != null){ throw new RuntimeException("单例不允许多个实例"); } } public static class SingleHolder{ private static Single_4 single_4 = new Single_4(); } public static Single_4 getInstance(){ return SingleHolder.single_4; } }
-
枚举模式
- 可以实现接口,但是不能被继承
- 可以像一个类一样正常被使用
- 无法通过反射对其进行破坏
-
public enum Single_5 { INSTANCE; public void getTest(){ } }
-
-
工厂方法模式
-
工厂方法定义
- 定义一个用于创建对象的接口,让其子类决定实例化哪一个类,工厂方法使一个类的创建延迟到其子类
- 一个产品派生出多个具体产品
-
应用场景
- 当你不知道使用对象的确切类型的时候
- 当你希望库或者框架为其提供扩展其内部组件的方法
- demo:QQ飞车的车的类型
-
主要优点
- 将产品和创建解耦
- 符合单一职责原则
- 符合开闭原则
-
demo:根据反射+注释实现
-
public interface Shape { void onDraw(); void getColor(); void getShape() ; }
import com.iflytek.yws.Shape; import com.iflytek.yws.ShapeType; @ShapeType(channelid = 3) public class Bar implements Shape { @Override @UiThread public void onDraw() { Log.v("YWS","--------Bar-------"); } @Override public void getColor() { Log.v("YWS","--------Bar------getShape-"); } @Override public void getShape() { Log.v("YWS","--------Bar------getShape-"); } }
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ShapeType { int channelid(); }
import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import dalvik.system.DexFile; public class ShapeFactoty { public HashMap<Integer,String> hashMap = new HashMap(); public ShapeFactoty(){ if (SingleHolder.shapeFactoty != null){ new Throwable("单例模式不允许多个创建多个实例!"); } } private static class SingleHolder{ private static ShapeFactoty shapeFactoty = new ShapeFactoty(); } public static ShapeFactoty getInstance(){ return SingleHolder.shapeFactoty; } public Shape create(int channelId){ try { String clazz = hashMap.get(channelId); Class c = Class.forName(hashMap.get(channelId)); return (Shape) c.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); }catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } return null; } public void init(){ List<String > classs = getClassName("com.iflytek.yws.shape"); for (int i = 0 ; i < classs.size() ; i++){ try { Class theClass = Class.forName(classs.get(i)); boolean hasAnn = theClass.isAnnotationPresent(ShapeType.class); if (hasAnn) { // 获取该注解对象 ShapeType myAnn = (ShapeType)theClass.getAnnotation(ShapeType.class); // 获取属性值 int id = myAnn.channelid(); hashMap.put(id,classs.get(i)); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } public List<String > getClassName(String packageName){ List<String >classNameList=new ArrayList<String >(); try { DexFile df = new DexFile(MyApplication.context.getPackageCodePath());//通过DexFile查找当前的APK中可执行文件 Enumeration<String> enumeration = df.entries();//获取df中的元素 这里包含了所有可执行的类名 该类名包含了包名+类名的方式 while (enumeration.hasMoreElements()) {//遍历 String className = (String) enumeration.nextElement(); if (className.contains(packageName)) {//在当前所有可执行的类里面查找包含有该包名的所有类 classNameList.add(className); } } } catch (IOException e) { e.printStackTrace(); } return classNameList; } }
调用实现如下:
ShapeFactoty.getInstance().create(3).getShape();
-
-
抽象工厂模式
-
定义
- 多个产品抽象产品,每个抽象产品能派生处多个具体抽象产品
- 一个工厂可以派生多个具体工厂类
- 每个具体的工厂可以派生多个具体的产品
-
应用场景
- 当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。
-
优缺点
-
它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
-
最大的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同产品配置
-
增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性
-
-
demo
-
-
建造者模式
-
定义
- 简单来说,就是一步步创建一个对象,它对用户屏蔽了里面构建的细节,但却可以精细地控制对象的构造过程。
-
应用场景
- Builder模式在ImageLoader和Rxjava中的体现
-
优缺点
- 优点
- 解耦产品的创建过程,有很好稳定性
- 符合开闭原则,业务相同情况下,扩展业务简单,只需简单配置
- 缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制
- 优点
-
demo
-
package com.iflytek.request.design.build; import com.iflytek.request.tool.LogY; public class RetrofitShape { private String color; private String shape; private String size; private String name; public RetrofitShape(String color, String shape, String size, String name) { this.color = color; this.shape = shape; this.size = size; this.name = name; } public void doStart() { LogY.v(toString()); } public static final class Builder { private String color; private String shape; private String size; private String name; public Builder() { } public Builder setColor(String str) { color = str; return this; } public Builder setShape(String str) { shape = str; return this; } public Builder setSize(String str) { size = str; return this; } public Builder setName(String str) { name = str; return this; } public RetrofitShape build() { return new RetrofitShape(color, shape, size, name); } } @Override public String toString() { return "RetrofitShape{" + "color='" + color + '\'' + ", shape='" + shape + '\'' + ", size='" + size + '\'' + ", name='" + name + '\'' + '}'; } }
RetrofitShape builder = new RetrofitShape.Builder().setColor("red").setName("yjJJJJJJ").setShape("").setSize("100").build();; builder.doStart();
-
-
原型模式
-
定义
- 原型实例指定创建对象的类型,通过拷贝这些原型创建新的对象
-
应用场景
- 一个对象需要提供给另一个对象访问使用,而且调用者可能改变其数值,就可以用原型模式进行clone,即对数据进行拷贝保护
-
优缺点
- 优点
- 比new创建对象性能好,且数据拷贝后,对数据保护
- 缺点
- 直接在内存汇总拷贝,不会实现构造函数
- 优点
-
demo
-
-
package com.iflytek.request.design.prototype; import androidx.annotation.NonNull; public class People implements Cloneable { public People(UserInfo userInfo, int type, int index){ this.userInfo = userInfo; this.index = index; this.type = type; } public UserInfo getUserInfo() { return userInfo; } public void setUserInfo(UserInfo userInfo) { this.userInfo = userInfo; } public int getType() { return type; } public void setType(int type) { this.type = type; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } @NonNull @Override protected People clone() throws CloneNotSupportedException { People clone = (People)super.clone(); UserInfo userInfo = this.userInfo.clone(); clone.setUserInfo(userInfo); return clone; // return (People)super.clone(); } @Override public String toString() { return "People{" + hashCode() + '\'' + "userInfo=" + userInfo + ", type=" + type + ", index=" + index + '}'; } UserInfo userInfo; int type; int index; }
package com.iflytek.request.design.prototype; import androidx.annotation.NonNull; public class UserInfo implements Cloneable{ public UserInfo(String name, String phone){ this.name = name; this.phone = phone; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @NonNull @Override protected UserInfo clone() throws CloneNotSupportedException { return (UserInfo)super.clone(); } @Override public String toString() { return "UserInfo{" + hashCode() + '\'' + "name='" + name + '\'' + ", phone='" + phone + '\'' + '}'; } String name; String phone; }
package com.iflytek.request.design.prototype; import android.util.Log; import com.iflytek.request.tool.LogY; public class Prototype { public static void test() throws CloneNotSupportedException{ UserInfo userInfo = new UserInfo("Yj","1333333"); People people = new People(userInfo,111111111,222222222); People clonePeople = people.clone(); LogY.v("people = "+people); LogY.v("clonePeople = "+clonePeople); userInfo.setName("yws"); LogY.v("people = "+people); LogY.v("clonePeople = "+clonePeople); } }
-
享元模式
-
定义
- 运用共享技术有效的支持大量细粒度对象
-
应用场景
- 系统之有大量相同对象
- 需要缓冲池的场景
-
优缺点
- 优点
- 如果有大量类对象,可以节约大量内存以及CPU资源
- 抽象出共同的对象,避免重复创建相同对象
- 缺点
- 加大了代码复杂的,需要分离出外部和内部状态
- 优点
-
demo
- https://www.runoob.com/design-pattern/flyweight-pattern.html
-
package com.iflytek.request.design.flyweight; import java.util.ArrayList; import java.util.HashMap; public class FlyWeight { public static void testFly() { new TreeNode(1, 1, FactoryFly.getTree("yj", "11111111111")); new TreeNode(1, 2, FactoryFly.getTree("yj", "2222222222")); new TreeNode(2, 1, FactoryFly.getTree("yws", "11111111111")); new TreeNode(2, 2, FactoryFly.getTree("yws", "222222222")); } public static class FactoryFly { public static HashMap<String, Tree> hashMap = new HashMap<>(); public static Tree getTree(String name, String date) { if (hashMap.containsKey(name)) { return hashMap.get(name); } Tree tree = new Tree(name, date); hashMap.put(name, tree); return tree; } } public static class Tree { private String name; private String date; public Tree(String name, String date) { this.name = name; this.date = date; } public String getName() { return name; } public String getDate() { return date; } } static class TreeNode { int x = 0; int y = 0; Tree tree; public TreeNode(int x, int y, Tree tree) { this.x = x; this.y = y; this.tree = tree; } public int getX() { return x; } public int getY() { return y; } public Tree getTree() { return tree; } } }
-
-
门面模式(外观模式)
-
定义
- 为一组接口提供了一个一致的接口,这个一致接口让这一组接口更容易使用,fasade模式定义的是一个高层接口
-
应用场景
- 医院挂号中的接待室,可以分别接入各个类别窗口
-
优缺
- 优点
- 用户和子系统解耦,隐蔽子系统逻辑
- 使用简单,简化用户与子系统的依赖关系,使得调用简单
- 缺点
- 不规范的编程,没有面向抽象编程,而是通过增加中间层,转换提供方接口
- 优点
-
demo
-
-
适配器模式
-
定义
- 将一个类的接口转换成用户希望的另一个接口,adapter使用原本不兼容的两个接口可以一起工作
-
应用场景
- 安卓适配器(Adapter)
-
优缺点
- 优点
- 符合单一职责原则
- 符合开闭原则
- 将目标和适配者类解耦
- 缺点
- 一次最多只能适配一个类
- 优点
-
demo
-
-
package com.iflytek.request.design.adapter.rcl; public class RecycleView { Adapter mAdapter; public void setAdapter(Adapter adapter) { mAdapter = adapter; onBindViewHolder(); getItemCount(); } public void onBindViewHolder() { mAdapter.bindViewHolder(); } public void getItemCount() { mAdapter.getItemCount(); } public abstract static class Adapter { public abstract void bindViewHolder(); public abstract int getItemCount(); } }
package com.iflytek.request.design.adapter.rcl; import com.iflytek.request.tool.LogY; public class TestAdapter extends RecycleView.Adapter{ @Override public void bindViewHolder() { LogY.v("bindViewHolder"); } @Override public int getItemCount() { LogY.v("getItemCount"); return 0; } }
package com.iflytek.request.design.adapter.rcl; public class Test { public static void testAdapter(){ RecycleView.Adapter adapter = new TestAdapter(); RecycleView rcy = new RecycleView(); rcy.setAdapter(adapter); } }
-
装饰器模式
-
定义
- 不改变对象的情况下,将附加功能添加到对象上
-
应用场景
- 扩展一个类的功能,或者给一个类添加附加的职责
-
优缺点
- 优点
- 不改变原有对象的情况下给一个对象扩展功能
- 符合开闭的设计原则
- 不同的组合可以实现不同的业务
- 缺点
- 多层装饰比较复杂。比如我们现在有很多层装饰,出了问题,一层一层检查,最后发现是最里层的装饰出问题了,想想工作量都害怕
- 优点
-
demo
-
package com.iflytek.request.design.decorator; import com.iflytek.request.tool.LogY; public class TestDecorator { public void init(){ Component component = new CreateComponent(); component = new Component_A(component); component = new Component_B(component); component.operation(); } public interface Component { void operation(); } public class CreateComponent implements Component { @Override public void operation() { LogY.v("主要的功能!!!"); } } public class Component_Main implements Component { Component createComponent = null; public Component_Main(Component createComponent){ this.createComponent = createComponent; } @Override public void operation() { createComponent.operation(); } } public class Component_A extends Component_Main { public Component_A(Component createComponent) { super(createComponent); } private void method_A() { LogY.v("A功能!!!"); } @Override public void operation() { this.method_A(); super.operation(); } } public class Component_B extends Component_Main { public Component_B(Component createComponent) { super(createComponent); } private void method_B() { LogY.v("B功能!!!"); } @Override public void operation() { this.method_B(); super.operation(); } } }
-
-
-
策略模式
-
定义
- 定义算法族,将其封装,在初始化,通过选择传入不同的算法,实现不同的策略
-
应用场景
- JDK中算法排序,根据传入不同的算法,实现不同的排序
-
优缺点
- 优点
- 算法可以根据传入选择进行切换,避免重复判断,扩展性好
- 缺点
- 策略对外暴露,策略的类会增多,代码臃肿
- 优点
-
demo
-
package com.iflytek.request.design.strategy; import com.iflytek.request.tool.LogY; public class StrategyTest { public void init(){ StrategyContext add = new StrategyContext(new AddStrategy()); LogY.v("++++++++++++" + add.executeStrategy(8,2)); StrategyContext subtrack = new StrategyContext(new SubtrackStrategy()); LogY.v("------------" + subtrack.executeStrategy(8,2)); StrategyContext multiply = new StrategyContext(new MultiplyStrategy()); LogY.v("***********" + multiply.executeStrategy(8,2)); } public class StrategyContext{ Strategy strategy; public StrategyContext(Strategy strategy ){ this.strategy = strategy; } //此类封装策略模式,根据传入参数,分发不同角色 public int executeStrategy(int a, int b){ return strategy.doOperation(a,b); } } public interface Strategy{ int doOperation(int a, int b); } public class AddStrategy implements Strategy{ @Override public int doOperation(int a, int b) { return a + b; } } public class SubtrackStrategy implements Strategy{ @Override public int doOperation(int a, int b) { return a - b; } } public class MultiplyStrategy implements Strategy{ @Override public int doOperation(int a, int b) { return a * b; } } }
-
-
-
模板方法模式
-
定义
- 定义一个算法骨架,将具体的算法实现放入子类去实现
-
应用场景
- 安卓Activity生命周期的复写实现
-
优缺点
- 优点
- 封装不可改变部分,扩展可变部分
- 行为由父类控制,子类实现
- 提取公共代码,便于维护
- 缺点
- 每个不同的实现都需要一个子类,类增多,使得系统边得庞大
- 优点
-
demo
-
-
观察者模式
-
定义
- 定义了对象之间一对多的依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化,所有依赖者都会收到通知
-
应用场景
- JDK:Observable
-
优缺点
- 优点
- 观察者和被观察者是抽象耦合的
- 建立一套触发机制
- 符合开闭原则
- 可在运行时建立对象之间的关系
- 缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
- 设计麻烦,设计不当会出现循环调用,系统崩溃
- 优点
-
demo
-
-
责任链模式
-
定义
- 为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
-
应用场景
- 登录请求
-
优缺点
- 优点
- 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息
- 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
- 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
- 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
- 缺点
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用
- 优点
-
demo
-
package com.iflytek.request.design.chain; import com.iflytek.request.tool.LogY; public class ChainTest { public void init(){ Request request = new Request.ReuestBuilder().loggedOn(true).isPermits(true).frequentOK(true).containsSensitiveWords(true).build(); Handler loggedOn = new LoggedOn(new IsPermits(null)); if (loggedOn.process(request)){ LogY.v("正常业务处理"); }else { LogY.v("访问异常"); } } abstract class Handler{ Handler next; public Handler(Handler next){ this.next = next; } public Handler getNext() { return next; } public void setNext(Handler next) { this.next = next; } abstract boolean process(Request request); } class LoggedOn extends Handler{ public LoggedOn(Handler next) { super(next); } @Override boolean process(Request request) { if (request.isLoggedOn()){ LogY.v("LoggedOn"); Handler handler = getNext(); if (null == handler){ return true; } if (handler.process(request)){ return true; } } return false; } } class IsPermits extends Handler{ public IsPermits(Handler next) { super(next); } @Override boolean process(Request request) { if (request.isPermits()){ Handler handler = getNext(); LogY.v("IsPermits"); if (null == handler){ return true; } if (handler.process(request)){ return true; } } return false; } } }
package com.iflytek.request.design.chain; class Request { private boolean loggedOn; public boolean isLoggedOn() { return loggedOn; } public void setLoggedOn(boolean loggedOn) { this.loggedOn = loggedOn; } public boolean isFrequentOK() { return frequentOK; } public void setFrequentOK(boolean frequentOK) { this.frequentOK = frequentOK; } public boolean isPermits() { return isPermits; } public void setPermits(boolean permits) { isPermits = permits; } public boolean isContainsSensitiveWords() { return containsSensitiveWords; } public void setContainsSensitiveWords(boolean containsSensitiveWords) { this.containsSensitiveWords = containsSensitiveWords; } private boolean frequentOK; private boolean isPermits; private boolean containsSensitiveWords; private String requestBody; private Request(boolean a, boolean b, boolean c, boolean d) { this.loggedOn = a; this.frequentOK = b; this.isPermits = c; this.containsSensitiveWords = d; } public static class ReuestBuilder { private boolean loggedOn; private boolean frequentOK; private boolean isPermits; private boolean containsSensitiveWords; public ReuestBuilder loggedOn(boolean loggedOn) { this.loggedOn = loggedOn; return this; } public ReuestBuilder frequentOK(boolean frequentOK) { this.frequentOK = frequentOK; return this; } public ReuestBuilder isPermits(boolean isPermits) { this.isPermits = isPermits; return this; } public ReuestBuilder containsSensitiveWords(boolean containsSensitiveWords) { this.containsSensitiveWords = containsSensitiveWords; return this; } public Request build() { return new Request(loggedOn, frequentOK, isPermits, containsSensitiveWords); } } }
-