博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
常用设计模式
阅读量:7167 次
发布时间:2019-06-29

本文共 9043 字,大约阅读时间需要 30 分钟。

工厂设计模式

  • 工厂设计模式,主要用于进行实例化对象时的解耦操作,避免使用new关键字实例化对象,通过反射,根据类名称动态创建对象
  • 示例:
package design;/**   *静态工厂模式   */public class Factory {/**   *构造方法私有化   */private Factory (){ }/**   * 获取指定类名称的对象   * @param className    * @param 
* @return T */public static
T getInstance(String className){ T object =null; try { object = (T) Class.forName(className).newInstance(); }catch (Exception e){ e.printStackTrace(); } return object; }}

动态代理模式

  • 动态代理模式,主要用于对同一接口子类的相同逻辑进行代理操作
  • 示例:
package design;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/**   * 动态代理模式   */public class DynamicProxy implements InvocationHandler {    private Object target;    /**     * 代理的目标对象     * @param target     * @return     */    public Object proxy(Object target){        this.target=target;        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);    }    /**     * 目标方法执行前执行     * @param object     */    public void before(Object object){        System.out.println("目标方法执行前执行");    }    /**     * 目标方法执行后执行     * @param object     */    public void after(Object object){        System.out.println("目标方法执行后执行");    }    /**     * Processes a method invocation on a proxy instance and returns     * the result.  This method will be invoked on an invocation handler     * when a method is invoked on a proxy instance that it is     * associated with.     * @param proxy     * @param method     * @param args     * @return     * @throws Throwable     */    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        this.before(proxy);        Object result =method.invoke(proxy,args);        this.after(result);        return result;    }}

单例模式一

  • 单例模式一:采用static final 修饰在类内部实例化的对象,保证对象的唯一性,此种方式,实在类加载的过程中实例化对象,无论是否使用,都会实例化。
  • 示例
package design;/**   * 单例模式一   */public class SingletonOne {    /**     * 实例化对象唯一     */    private static final SingletonOne INSTANCE =new SingletonOne();    /**     * 构造方法私有化     */    private SingletonOne(){    }    /**     * 获取单例对象     * @return     */    public static SingletonOne getInstance(){        return INSTANCE;    }}

单例模式二

  • 单例模式二:采用volatile关键字修饰实例化对象,并通过同步锁(锁Class)的形式,保证实例化对象的唯一性,此方式在第一次使用时进行实例化
  • volatile关键字修饰的变量与普通变量的读取方式不同
01.png
volatile定义的变量,将直接使用原始数据进行处理,更改后立即生效
  • 示例
package design;/**   * 单例模式二   */public class SingletonTwo {    /**     * 使用volatile关键字修饰单例对象     * volatile定义的变量,将直接使用原始数据进行处理,更改后立即生效     */    public static volatile SingletonTwo instance;    /**     * 构造方法私有化     */    private SingletonTwo(){    }    /**     * 获取单例对象     * @return     */    public static SingletonTwo getInstance(){        if(instance ==null){            //通过同步锁住当前类,来保证线程安全,并提高性能,若直接同步该方法,会大大降低性能            synchronized (SingletonTwo.class){                if (instance ==null){                    instance =new SingletonTwo();                }            }        }        return instance;    }}

单例模式三

  • 单例模式三:基于Jvm类加载机制实现单例
  • 示例
/** * 单例模式三 */public class ClassSingletonDemo {    /**     * 构造方法私有化     */    private ClassSingletonDemo(){};    /**     * 静态方法获取实例     */    public static ClassSingletonDemo getInstance(){        return SingletonHandler.singleton;    }    /**     * 内部静态类保证只初始化一次     */    private static class SingletonHandler {        private static ClassSingletonDemo singleton = new ClassSingletonDemo();        static {            System.out.println("This's innerClass's static code block");        }    }}

单例模式四

  • 单例模式四:基于Enum类型的加载机制实现单例
  • 示例
/** * 单例模式四 */public class EnumSingletonDemo {    /**     * 构造方法私有化     */    private EnumSingletonDemo(){}    /**     * 静态方法获取实例     */    public static EnumSingletonDemo getInstance(){        return Singleton.INSTANCE.getInstance();    }    /**     * 私有枚举,只被JVM加载一次,只实例化一次     */    private enum Singleton{        INSTANCE;        private EnumSingletonDemo singleton;        Singleton(){            singleton = new EnumSingletonDemo();        }        public EnumSingletonDemo getInstance(){            return singleton;        }    }}

中介者模式

(转载自)
  • 中介者模式的定义:用一个中介对象来封装一些列的对象交互,中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式解决问题的思路很简单,就是通过引入一个中介对象,让其他对象只与中介对象交互,而中介对象知道如何和其他所有对象的交互,这样对象之间的交互关系就没有了,从而实现了对象之间的解耦。由此,我们也可以看出一个问题,那就是中介对象控制着整个系统的逻辑,它会过于复杂,这是一个缺点。中介者模式的本质是封装交互:

    • (1)对象在自身状态发生改变时报告给中介对象;
    • (2)中介对象控制着整个系统的逻辑,它知道如何与所有对象交互;
    • (3)对象需要对中介对象发出的请求作出回应。
  • 中介者模式中的角色:

    • Mediator:中介者接口,定义各个同事之间交互所需要的方法;
    • ConcreteMediator:具体的中介者,它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系;
    • Colleague:所有同事对象的父类,一般实现成抽象类,主要负责约束同事对象的类型,并负责实现一些公共功能;
    • ConcreteMediator:具体的同事类,实现自己的业务,当需要与其他同事对象通信时,就与持有的中介者通信,中介者会负责与其他同事的交互。在标准的中介者模式中,将使用中介者来交互的那些对象叫做同事类,它们继承自相同的父类,所以叫做同事。正是由于它们之间的交互很复杂,所以才产生了把这些交互关系分离出去,让中介者来处理。
  • 示例:

    • 以电脑来看电影为例子,首先光驱从光盘中读取数据,然后通知CPU将数据分离成音频和视频,CPU处理完毕后再分别将数据传送给声卡和显卡进行播放。从上面的描述的中发现,光驱盒CPU是耦合的,CPU又和声卡显卡是耦合的,怎么解耦的呢?如果使用中介者模式,通过引入主板作为中介者,所有的对象都与主板交互,那么播放电影的流程就变成了这样:

      • (1)光驱从光盘读取到数据,通知主板,数据准备好了;
      • (2)主板收到光驱的请求后,将原始数据传给CPU,让它将数据分离成音频和视频;
      • (3)CPU将数据分离后,通知主板,数据分离完毕;
      • (4)主板收到CPU通知后,分别将音频和视频传给声卡和显卡;
      • (5)声卡和显卡同时播放。

这样一个过程中,所有的类只与主板耦合,而不与其他类保持关系,做到了解耦,而且过程很清晰。实际上计算机硬件就是这样通信的,只不过更复杂一些,所以这些东西都是相通的,重要的是思想。

  • Java实现:

    • 同事对象的父类
package design;/** * 同事对象的父类,一般实现成抽象类,用于约束同事对象的类型 * 同时实现一些功能公共方法,例如持有中介者对象 */public abstract class Colleague {    //所有的同事对象都需要持有中介对象    private Mediator mediator;    public Colleague(Mediator mediator) {        this.mediator = mediator;    }    public Mediator getMediator() {        return mediator;    }}
  • 中介者接口
package design;/** * 中介者接口 */public interface  Mediator {    /**     * 同事对象自身状态改变时,通过这个方法通知中介者对象     * @param obj     */    public void changed(Colleague obj);    /**     * 中介者对象需要知道所有同事对象     * @param instance     */    public void setCDDriver(CDDriver instance);    public void setCPU(CPU instance);    public void setVideoCard(Video instance);    public void setSoundCard(Sound instance);}
  • 光驱类
package design;/** * 光驱类,负责从光盘中读取数据 */class CDDriver extends Colleague {    //从光盘读取的原始数据    private String originData;    public CDDriver(Mediator mediator) {        super(mediator);    }    public String getOriginData() {        return originData;    }    /**     * 读取光盘数据,一旦读取到数据,就要通知中介者对象数据已经准备好了     */    public void readCD(String originData) {        this.originData = originData;        //通知中介对象,自己的状态发生了改变        getMediator().changed(this);    }}
  • CPU类
package design;/** * CPU类,负责将原始数据分离成音频和视频 */public class CPU extends Colleague {    //声音数据    private String soundData;    //视频数据    private String videoData;    public CPU(Mediator mediator) {        super(mediator);    }    public String getSoundData() {        return soundData;    }    public String getVideoData() {        return videoData;    }    /**     * 将数据分离,同时通知中介者对象,数据已经分离     * @param originData     */    public void sperateData(String originData) {        this.soundData = originData.split(",")[1];        this.videoData = originData.split(",")[0];        //通知中介对象,自己的状态发生了改变        getMediator().changed(this);    }}
  • 显卡类,播放视频
package design;/** * 显卡类,播放视频 */public class Video extends Colleague {    public Video(Mediator mediator) {        super(mediator);    }    public void showVideo(String videoData) {        System.out.println("正在观看:" + videoData);    }}
  • 声卡类
package design;/** * 声卡类,播放声音 */public class Sound extends Colleague {    public Sound(Mediator mediator) {        super(mediator);    }    public void showSound(String soundData) {        System.out.println("解说:" + soundData);    }}
  • 主板类
package design;/** * 主板类,实现中介者 */public class MainBoard implements Mediator {    private CDDriver cd;    private CPU cpu;    private Video vc;    private Sound sc;    public void setCDDriver(CDDriver instance) {        this.cd = instance;    }    public void setCPU(CPU instance) {        this.cpu = instance;    }    public void setVideoCard(Video instance) {        this.vc = instance;    }    public void setSoundCard(Sound instance) {        this.sc = instance;    }    /**     * 当同时对象自身状态发生改变时,调用此方法通知中介者对象     * 中介者对象在进行逻辑控制,与其他同对象交互     */    public void changed(Colleague obj) {        //如果是光驱类,需要通知CPU去分离数据        if(obj instanceof CDDriver) {            String originData = ((CDDriver) obj).getOriginData();            this.cpu.sperateData(originData);        }else if(obj instanceof CPU){//如果是CPU类,需要通知声卡和显卡去播放            String videoData = ((CPU) obj).getVideoData();            String soundData = ((CPU) obj).getSoundData();            this.vc.showVideo(videoData);            this.sc.showSound(soundData);        }    }}
  • 客户端
package design;/** * 客户端 */public class Client {    public static void main(String[] args) {        Mediator mediator = new MainBoard();        CDDriver cd = new CDDriver(mediator);        CPU cpu = new CPU(mediator);        Video vc = new Video(mediator);        Sound sc = new Sound(mediator);        mediator.setCDDriver(cd);        mediator.setCPU(cpu);        mediator.setSoundCard(sc);        mediator.setVideoCard(vc);        //光驱读数据,通知中介者,中介者通知CPU去分离数据,CPU分离数据完成,通知中介者,中介者通知声卡和显卡播放        cd.readCD("终结者,终结者音频");    }}
你可能感兴趣的文章
两个div在同一行,两个div不换行
查看>>
ARM-Linux配置DHCP自动获取IP地址
查看>>
文本框改变事件(不用失去焦点)
查看>>
【求助】怎样实如今并肩看中增加代码啊
查看>>
mysql 性能优化方案
查看>>
Java并发编程:volatile关键字解析
查看>>
Oracle Alert - APP-ALR-04108: SQL error ORA-01455
查看>>
【转】在linux内核中读写文件 -- 不错
查看>>
http put post请求区别
查看>>
android EventBus的简单使用
查看>>
在.net中使用GAC
查看>>
EasyExcel导入工具(SpringMVC下使用)
查看>>
【转载】查找怪数据数组的内存分布和地址(天龙八部)
查看>>
敏捷生活练习第14次活动:学会感恩
查看>>
Windows Azure Cloud Service (15) 多个VM Instance场景下如何处理ASP.NET Session
查看>>
Android学习笔记(7)————Android中的消息机制
查看>>
重装系统后,硬盘分区丢失的解决办法
查看>>
玩转轻巧型C/C++ IDE之C-Free(配置GCC、Visual C++、Borland C++编译器)
查看>>
利用Delphi编写IE扩展
查看>>
邮箱里边添加自己的网站首页
查看>>