设计模式
目录
一 单利模式
用EventBus的创建方式为例子
public class EventBus {
private static volatile EventBus defaultInstance;
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
}
构造方法私有,静态方法得到实例
volatile 关键字:告诉不同的线程 不要拿寄存器的值,要拿主存的值
synchronized 关键字:可以同步与 方法 或者 代码块
优化点
- 优点
- 提供了对唯一实例的受控访问;
- 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能;
- 可以根据实际情况需要,在单例模式的基础上扩展做出双例模式,多例模式;
- 缺点
- 单例类的职责过重,里面的代码可能会过于复杂,在一定程度上违背了“单一职责原则”。
- 如果实例化的对象长时间不被利用,会被系统认为是垃圾而被回收,这将导致对象状态的丢失。
二 工厂模式
用汽车为例子
1. 先建一个 Car 的抽象类
public abstract class Call{
// 启动 开车
public abstract Start();
}
2. 比如 有 奥迪, 有宝马…
// 奥迪车类
public AodiCar extends Car{
public void Start(){
system.out.println("奥迪车启动了")
};
}
// 宝马车类
public BWMCar extends Car{
public void Start(){
system.out.println("宝马车启动了")
};
}
3.建一个工厂生产
public class CarFactory{
//此处传递过来的参数是 包.类名
public static Car getInstance(Class clazz) {
Car car = null;
try {
//利用反射 实例化对象
car = (Car)Class.forName(clazz.getName).newInstance();
}catch(Exception e) {
e.printStackTrace();
}
return car;
}
}
4. 测试
Car aodiCar= CarFactory.getInstance(AodiCar.class)
Car bmwCar= CarFactory.getInstance(BWMCar.class)
aodiCar.start();
bmwCar.start();
5.场景
比如Retrfit中有很多个Service 你完全可以用工厂模式做
三 观察者模式
场景很多, 比如EventBus , Rxjava 等等
需要知道的东西
- 抽象被观察者角色:
也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。 - 抽象观察者角色:
为所有的具体观察者定义一个接口,在得到主题通知时更新自己 - 具体被观察者角色:
也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知 - 具体观察者角色:
实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
开始写例子 比如银行向每个客户发送推广广告
定义一个抽象被观察者接口
public interface Observerable{
// 用来注册观察者 也就是注册用户
void register(Observe o);
// 移除观察者 也就是移除用户
void unRegister(Observe o)
//通知 也就是发送推广广告
void notifyAll();
}
定义一个抽象观察者
public interface Observe{
// 收到消息 也就是收到银行的广告通知
void recivered(String msg);
}
定义一个抽象被观察者接口的实现类
public class ObserverableImpl implements ObserveAble{
// 这个是存贮所有注册过的观察者
private ArrayList<Observe> list;
// 记录要下发的消息
private String message;
public ObserverableImpl(){
list = new ArrayList();
}
// 添加
@Override
public void register(Observe o){
if(!list.contains(o)){
list.add(o);
}
}
//移除
@Override
public void unRegister(Observe o){
if(list.contains(o)){
list.remove(o);
}
}
//通知
@Override
public void notifyAll(){
for(int i=0;i++;i<list.size()){
list.get(i).recivered(message); // 然后调用 观察者的方法
}
}
// 给外界暴露的方法 设置消息并且通知
public void setInfomation(String s) {
this.message = s;
//消息更新,通知所有观察者
notifyAll();
}
}
具体观察者实现类
public class ObserveImpl(){
private String name;
public ObserveImpl(String name){
this.name=name;
}
@Override
public void recivered(String msg){
//收到消息 去做自己的事情
System.out.println(name + " 收到推送过来的消息: " + message);
}
}
测试
// 银行
Observerable obserebale = new ObserverableImpl();
//用户
Observer xiaoming = new ObserveImpl("小明");
Observer xiaohong = new ObserveImpl("小红");
obserebale.register(userZhang);
obserebale.register(userLi);
// 调用Observerable的发送消息
obserebale.setInfomation("你中奖100w");
打印的日志是:
小明收到推送的消息你中奖100w
小红收到推送的消息你中奖100w
四 建造者模式 (builder模式)
典型的例子 (很多)
- android 中的dialog(最典型了)
- okhttp 的 OkHttpClient.Builder 和 Request.Builder
- EventBus 的 EventBusBuilder
例子
public class Person {
private String mName;
private int mAge;
private String mAddress;
private Person(Builder builder) {
mName = builder.mName;
mAge = builder.mAge;
mAddress = builder.mAddress;
}
public static final class Builder {
private String mName;
private int mAge;
private String mAddress;
public Builder() {
}
public Builder setName(String name) {
mName = name;
return this;
}
public Builder setAge(int age) {
mAge = age;
return this;
}
public Builder setAddress(String address) {
mAddress = address;
return this;
}
public Person build() {
return new Person(this);
}
}
}
使用
Person person = new Person.Builder().setAddress("河北邯郸").setName("nzy").setAge(27).build();
Studio 插件 可以一键生成builder格式代码 InnerBuilder 插件
优缺点(参考)
- 优点:
- 不需要知道产品内部的组成细节,产品与创建过程解耦
- 分步组装产品,使得产品的创建过程更精细更清晰
- 容易扩展,新产品只需要新建一个建造者即可
- 缺点:
- Builder模式创建的产品差异性小,使用范围受限制
- 不同的产品会产生多个建造者和指挥者
五 动态代理模式
他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
场景:
android中的hook技术,有些插件化技术,spring中通过动态代理实现了aop(切面编程),retrofit.create
以retrofit为例子
需要代理的类(ApiService)
public interface ApiService
{
@GET("/heiheihei")
public void add(int a, int b);
}
}
代理类
class MyInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Integer a = (Integer) args[0];
Integer b = (Integer) args[1];
System.out.println("方法名:" + method.getName());
System.out.println("参数:" + a + " , " + b);
GET get = method.getAnnotation(GET.class);
System.out.println("注解:" + get.value());
return null;
}
}
开始代理
ApiService service = (ApiService) Proxy.newProxyInstance(ApiService.class.getClassLoader(), new Class<?>[]{ITest.class},new MyInvocationHandler())
六 装饰着模式
动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案。
场景: I/o流
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("..")));
构成
- 抽象构件类(Component):给出一个抽象的接口,用以规范准备接收附加责任的对象
- 具体构件类(ConcreteComponent):定义一个具体的准备接受附加责任的类,其必须实现Component接口。
- 装饰者类(Decorator):持有一个构件(Conponent)对象的实例,并定义一个和抽象构件一致的接口。
- 具体装饰者类(Concrete Decoratator):定义给构件对象“贴上”附加责任。