美文网首页
常用设计模式

常用设计模式

作者: iEvans | 来源:发表于2017-04-03 17:32 被阅读0次

    工厂设计模式

    • 工厂设计模式,主要用于进行实例化对象时的解耦操作,避免使用new关键字实例化对象,通过反射,根据类名称动态创建对象
    • 示例:
    package design;
    /**
       *静态工厂模式
       */
    public class Factory {
    /**
       *构造方法私有化
       */
    private Factory (){
    
     }
    /**
       * 获取指定类名称的对象
       * @param className    * @param <T>
       * @return T
       */
    public static <T> 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;
        }
    }
    

    中介者模式

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

    相关文章

      网友评论

          本文标题:常用设计模式

          本文链接:https://www.haomeiwen.com/subject/cwloottx.html