设计模式初学

xiaoxiao2021-02-27  338

设计模式基础

选择恰当的设计模式可以大大提高代码质量,可以说是优秀程序员编程智慧的产物。设计模式巧妙运用java基础知识:

多态:动态绑定 。。。(待补充,觉得最核心的就是多态)

单例模式

本质:确保类的实例化对象有且仅有一个应用:配置文件、日志、缓存、线程池等优点:避免过多占用资源或者数据同步问题

分类:

饿汉模式:静态化实例跟随类一同加载,无论是否在外部创建实例 step1:实例由构造方法创建,故改写构造方法(public -> private) 确保外部不能随意调用 step2:创建用于返回的私有静态实例,静态确保了唯一性 step3:返回实例的getInstance( )方法

懒汉模式:只是声明静态实例,只有当用户获取时才判断并创建实例 step1:构造方法私有化 step2:声明类的唯一实例 step3:获取实例方法

区别: 是否在内部进行实例化


工厂模式

目的:实现对象间的低耦合特点: 对象的创建由工厂负责 客户类产品成员面向接口,通过多态获取各工厂的产品 可以按照需求指定特定工厂来生产产品技术支持: 反射,class Properties/File.properties简单工厂模式: 所有的产品均由一个工厂生产,根据客户端要求生产出特定的产品,其缺点就是大大增加了工厂类的负担 class Factory{ public Product getProduct1(){ return new Product1(); } public Product getProduct2(){ return new Product2(); } } 抽象工厂模式: 产品:接口派生出各类产品 eg : class Product1 implements Product class Product2 implements Product工厂:接口派生出用于生产各类产品的工厂 interface ProductFactory{ public Product getProduct(); } class Product1Factory implements ProductFactory{ @override public Product getProduct(){ return new Product1(); } } class Product1Factory implements ProductFactory{ @override public Product getProduct(){ return new Product2(); } }

3.客户:创建工厂获得产品 eg:Product p = Product1Factory.getProduct( );


观察者模式

使用场景: 对象间存在依赖关系(理解成星型依赖)当 中心变化时需要其余周围对象及时更新自己。最近学习MQTT协议感觉观察者模式比较适用。

使用方法: 观察者:

//更新方法: public void update()

被观察者:

//维护一个观察者列表 private List<Watcher> watcherList = new ArrayList<Watcher>(); //添加观察者方法 public void addWatcher(Watcher watcher); //删除观察者方法 public void delWatcher(Watcher watcher); //通知观察者方法 public void notifyWatchers();

推拉方式 推方式:被观察者维护一个自己的状态(可以考虑JavaBean),当状态发生改变时主动将状态发送给观察者。适用于被观察者比较复杂,观察者必须获得一些信息的情况。 拉模式:观察者主动从被观察者处获得状态,只是被观察者需要提供一个状态获取接口。

使用java.util.Observable和java.util.Observer

//源码不多,直接粘过来 public class Observable { private boolean changed = false; private Vector<Observer> obs = new Vector(); public synchronized void addObserver(Observer paramObserver) { if (paramObserver == null) { throw new NullPointerException(); } if (!obs.contains(paramObserver)) { obs.addElement(paramObserver); } } public synchronized void deleteObserver(Observer paramObserver) { obs.removeElement(paramObserver); } public void notifyObservers() { notifyObservers(null); } public void notifyObservers(Object paramObject) { Object[] arrayOfObject; synchronized (this) { if (!changed) { return; } arrayOfObject = obs.toArray(); clearChanged(); } for (int i = arrayOfObject.length - 1; i >= 0; i--) { ((Observer)arrayOfObject[i]).update(this, paramObject); } } public synchronized void deleteObservers() { obs.removeAllElements(); } protected synchronized void setChanged() { changed = true; } protected synchronized void clearChanged() { changed = false; } public synchronized boolean hasChanged() { return changed; } public synchronized int countObservers() { return obs.size(); } } public abstract interface Observer { public abstract void update(Observable paramObservable, Object paramObject); }

代理模式

代理十分好理解就是代替被代理的对象完成一些行为,类比现实生活中的销售代理,就是为厂家去销售产品,而不是只有厂家直销一种方式。 厂家: 我们映射为被代理对象、真实对象。 销售代理: 我们映射为代理对象,它具有真实对象的行为,即有相同的接口实现。

粗糙例子一个: 厂家授权代理负责产品的销售(实现相同接口) 代理按照厂家吩咐对外有定价(接口中具体实现比厂家更细致) 代理下单,厂家发货(最终仍然使用厂家的接口实现)

/* * sell product interface */ public interface sellProduct(){ public void sell(); } /* * factory */ public class Factory implements sellProduct{ @Override public void sell(){ System.out.println("sell a product"); } } /* * proxy */ public class Proxy implements sellProduct{ private double price; //real object private Factory factory; public Factory getFactory() { return factory; } public void setFactory(Factory factory) { this.factory = factory; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public void sell(){ if(price >= 9999) factory.sell(); else if(price > 0 && price < 9999) System.out.println("cannot afford"); else System.out.println("don't joke me"); } } /* * deal */ public static void main(Stirng[] args){ Proxy proxy = new Proxy(); Factory factory = new Factory(); proxy.setFactory(factory); proxy.setPrice(9999); proxy.sell(); }

动态代理模式

在代理模式的基础之上运用反射技术。 当前常用的动态代理模式是JDK动态代理和CGLIB动态代理

JDK使用过程很简便:

实现java.lang.reflect.InvocationHandler建立代理对象和真实对象之间的关系 private real object; bind( );实现代理逻辑方法: invoke( );

简单粗糙例子一个,只列出以上三步:

public class JDKProxy implements InvocationHandler { // real object private Object target; /* * step1: create relation between proxy object and real object * * @param real object * * @return proxy object */ public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /* * step2: proxy method * @param proxy object * @param method * @param arguments * @return proxy result */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ System.out.println("enter into proxy logical method"); System.out.println("before invoke real object"); Object obj = method.invoke(target, args); System.out.println("after invoke real object"); return obj; } }

CGLIG动态代理 与JDK类似但是不同之处在于JDK代理的类必须实现接口,而CGLIB则是通过生成被代理类的子类,通过增强方法覆盖父类方法

增强方法获得被代理对象,以被代理类为父类。实现代理逻辑方法

简单粗糙例子

public class CGLIBProxy implements MethodInterceptor { public Object getProxy(Class realObject) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(realObject); enhancer.setCallback(this); return enhancer.create(); } /* * implements logical proxy method * * @param proxy object * * @param method???? * * @param method arguements * * @param proxy method * * @return result */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("before call real object"); Object result = methodProxy.invokeSuper(proxy, args); System.out.println("after call real object"); return result; } }

适配器模式

实践出真知,经历的积累就会形成一个人阅历,对待事物有不同深度的理解。 对适配器模式的学习理解,恰恰经历了马哲辩证法中知识与实践相互促进的过程(扯远了)

初识:适配器模式就像是视频线转换口,笔记本上只有HDMI口,而显示器只有VGA口,现在没有可以直接相连的线。所以需要淘一个东西把VGA的口“改造”一下,让笔记本以为显示器就是提供的HDMI插口,于是连接工作。验证:初识只是举了一个形象的例子,算是将抽象的概念简单的形象化一下。实践中,才深刻体会到适配器模式的意义。 IC卡表向web应用迁移,将原有的MFC客户端的工作迁移到浏览器上,使用的仍然是厂家提供的操作库——原已有接口 浏览器通过ActiveX调用底层接口,ActiveX采用ATL开发生成dll,在该dll中调用库接口实现对外的接口——适配后目标接口 用户可以使用JS直接引入ActiveX,并使用新接口强化初识认知,适配器模式两大要点: 用已有接口实现实现适配接口

装饰器模式

和适配器模式类似,区别在于适配器模式按照需要改造接口,而装饰器模式保留接口原貌但是功能进行增强。

转载请注明原文地址: https://www.6miu.com/read-3163.html

最新回复(0)