精华内容
下载资源
问答
  • 设计模式六大原则: 单一职责原则:就一个类仅有一个引起它变化的原因,即类承担的职责单一性; 开放封闭原则:类、模块、函数等应该是可以扩展的,但是不可修改。换句话说,就是面对需求的改变要尽可能地保证...

    设计模式六大原则:

    • 单一职责原则:就一个类仅有一个引起它变化的原因,即类承担的职责单一性;

    • 开放封闭原则:类、模块、函数等应该是可以扩展的,但是不可修改。换句话说,就是面对需求的改变要尽可能地保证相对稳定,尽量通过扩展的方式而不是修改原有的代码来实现。

    • 里氏替换原则:所有引用基类(父类)的地方必须透明地使用其子类对象。换句话说,就是尽量把父类设计为抽象类或者接口,在运行时子类实例替换父类实例,在扩展时通过增加一个新的子类实现;

    • 依赖倒置原则:高层模块不应该依赖低层模块,两者都应该依赖于抽象。换句话说,就是模块间的依赖通过抽象发生,实现类之间不发生直接依赖关系,其依赖关系是通过接口或者抽象类产生。

    • 迪米特原则:一个软件实体应当尽可能少地与其他实体发生相互作用。换句话说,就是通过引入一个合理的第三者来降低现有对象之间的耦合度,同时在设计类时尽量降低成员的访问权限。

    • 接口隔离原则:一个类对另一个类的依赖应该建立在最小接口上。换句话说,就是为各个类建立专用的接口,而不要试图建立一个庞大的接口供所有依赖它的类调用,同时接口中的方法尽量少且少用public修饰,以提高内聚和减少对外交互。

    1. 代理模式

     代理模式又称委托模式,它是结构型模式的一种,所谓结构型模式,是指从程序的结构上解决模块之间的耦合问题。在现实生活中,类似代理模式的场景非常多,比如代购、代理上网等,它的定义为:为其他对象提供一种代理以控制对这个对象的访问。换句话来说,就是通过代理来实现对某个对象的访问。代理模式UML类图如下:
    在这里插入图片描述
     在代理模式中有如下角色:

    • Subject:抽象主体类,它负责声明真实主体与代理的共同接口方法;
    • RealSubject:真实主题类,继承于Subject,是代理类所代表的真实主题;
    • Proxy:代理类,继承于Subject,持有对真实主题类的引用。客户端就是通过这个代理类间接地调用真实主题类的方法。

    1.1 代码实现

     在Android开发中,代理模式是一种较为常见的设计模式,比如基于Binder的跨进程通信机制就是基于代理模式实现的,其中,IInterface接口就是代码模式中的Subject,它声明了一些公共方法;远程服务端的Binder实体对象就是代理模式中的RealSubject,它继承于IInterface且实现了这些公共方法;本地代理对象BinderProxy就是Proxy,它也继承于IInterface但是没有实现这些公共方法,而是持有远程服务端Binder实体对象的引用。接下来,我们就模拟这种Binder机制来了解代理模式的实现思路。

    (1)IInterface,抽象主体类

    /** 抽象主体类
     * author : jiangdg
     * date   : 2020/1/31 10:23
     * desc   : 声明真实主题和代理的共同接口方法
     *  本例为将加运算放在远程服务端实现
     * version: 1.0
     */
    public interface IInterface {
        int add(int x, int y);
    }
    

    (2)Binder,真实主题类

    /** 真实主题类
     * author : jiangdg
     * date   : 2020/1/31 10:23
     * desc   : 为IInterface的中的方法具体实现
     * 本例中表示远程Binder实体,是真正的实现
     * version: 1.0
     */
    public class Binder extends IInterface {
        @Override
        public int add(int x, int y) {
            return x + y;
        }
    }
    

    (3)BinderProxy,代理类

    /** 代理类
     * author : jiangdg
     * date   : 2020/1/31 10:23
     * desc   : 持有远程Binder实体对象的引用,客户端就是通过这个代理对象
     *  实现对远程Binder对象的访问
     * version: 1.0
     */
    public class BinderProxy extends IInterface {
        private IInterface mBinder;
        
        public BinderProxy(IInterface binder) {
            mBinder = binder;
        }
        
        @Override
        public int add(int x, int y) {
            // 调用远程Binder的add方法实现加运算
            return mBinder.add(x, y);
        }
    }
    

     接下来,我们就来看客户端如何通过BinderProxy代理类实现对远程Binder对象的方法的访问,相关代码如下:

    // 创建代理类,需要传入远程Binder对象
    // 这个过程即为为远程Binder对象创建代理
    IInterface proxy = new BinderProxy(new Binder());
    // 执行加运算。
    // 虽然调用的是代理类的add方法,但是实际运算操作是在远程Binder对象的add方法
    int result = proxy.add(1, 2)
    

    注:实际上Binder机制远比上述描述的复杂,本文只是为了演示代理模式,如果想进一步了解基于Binder机制的IPC通信,可看我这篇博文《从Android6.0源码的角度剖析Binder工作原理

    1.2 使用场景

     代理模式的优点在于使得模块之间真正的解耦,即真实主题类RealSubject只负责实现实际的业务逻辑,不用关系其他非本职的工作,当真实主题类发生变化时,由于它和代理类均实现了公共接口,因此代理类Proxy可以不做任何修改就能够使用。基于此,代理模式主要有以下几种使用场景:

    • 远程代理

     为一个对象在不同的地址空间提供局部代表,这样系统可以将Server部分的实现隐藏;

    • 虚拟代理

     使用一个代理对象表示一个十分耗费资源的对象并在真正需要时才创建;

    • 安全代理

     用来控制真实对象访问时的权限。一般用于真实对象有不同的访问权限场景。

    2. 静态代理与动态代理

     从编码的角度来说,代理模式分为静态代理和动态代理。在第一小节中演示的例子就是静态代理,即在代码运行前就已经存在了代理类的class编译文件,换句话来说,就是在代码运行前我们就知道BinderProxy是Binder的代理;而动态代理是指在代码运行前我们并不知道谁来代理Binder对象,而是需要在代码运行时通过反射来动态地生成代理类的对象,也就是说,我们在编码阶段无需知道代理谁,代理谁将会在代码运行时决定。Java提供了动态地代理接口InvacationHandler,实现该接口需要重写invoke方法。下面我们将第一小节的案例改为动态代理,具体步骤如下:

    (1)创建动态代理类

    public class DynamicCalculate implements InvacationHandler {
        // 指向被代理的对象
        private Object obj;
        
        public DynamicCalculate(Object obj) {
            this.obj = obj;
        }
        
        // 重写invoke方法
        // 通过反射调用被代理对象的方法
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) 
        		throws Throwable{
            Object result = method.invoke(obj, args);
            return result;
        }
    }
    

    (2)客户端动态创建Binder的代理类

    public class Client {
        public static void main(String[] args) {
            IInterface mBinder = new Binder();
            // 1. 创建动态代理
            // 需要传入远程Binder对象
            DynamicCalculate dynamicCalculate = new DynamicCalculate(mBinder);
            // 2. 动态创建Binder对象的代理类
            // 需要传入Binder类的ClassLoader
            ClassLoader loader = mBinder.getClass().getClassLoader();
            IInterface binderProxy = (IInterface)Proxy.newProxyInstance(loader, new Class[]
                                               {IInterface.class}, dynamicCalculate);
            // 3. 通过代理访问远程Binder的方法
            int result = binderProxy.add(1, 2);
        }
    }
    

    静态代理中的代理类是在编码阶段确定的;动态代理中的代理类是在运行时确定的。

    展开全文
  • 代理模式是常用的结构型设计模式之一,当无法直接访问某个...根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理、远程代理、虚拟代理、缓冲代理等,它们应用于不同的场合,满足用户的不同需求。

    PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN。因为CSDN也支持MarkDown语法了,牛逼啊!

    【工匠若水 http://blog.csdn.net/yanbober】 阅读前一篇《设计模式(结构型)之享元模式(Flyweight Pattern)》http://blog.csdn.net/yanbober/article/details/45477551

    概述

    代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理、远程代理、虚拟代理、缓冲代理等,它们应用于不同的场合,满足用户的不同需求。

    这里写图片描述

    核心

    概念: 给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

    代理模式结构重要核心模块:

    Subject(抽象主题角色)

    它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。

    Proxy(代理主题角色)

    它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主题;代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。通常,在代理主题角色中,客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象中的操作。

    RealSubject(真实主题角色)

    它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。

    代理模式分类:

    代理模式根据其目的和实现方式不同可分为很多种类,其中常用的几种代理模式简要说明如下:

    远程代理(Remote Proxy)

    给一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又称为大使(Ambassador)。

    虚拟代理(Virtual Proxy)

    如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。

    保护代理(Protect Proxy)

    控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。

    缓冲代理(Cache Proxy)

    为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。

    智能引用代理(Smart Reference Proxy)

    当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等。

    使用场景

    代理模式的类型较多,不同类型的代理模式有不同的优缺点,它们应用于不同的场合:

    • 当客户端对象需要访问远程主机中的对象时可以使用远程代理。

    • 当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。

    • 当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理。通过使用缓冲代理,系统无须在客户端每一次访问时都重新执行操作,只需直接从临时缓冲区获取操作结果即可。

    • 当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理。

    • 当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。

    程序猿实例

    简单的实例:

    如下图片结构就是一个代理模式的UML图:

    这里写图片描述

    如下是一个入门代理模式的简单示例,遵循了代理模式的几大核心模块。我们以程序猿买 港版MacBook为例来说明代理模式。

    package yanbober.github.io;
    
    //抽象对象角色
    interface IMacBook {
        void buyIt();
    }
    //目标对象角色
    class HangKangMacBook implements IMacBook {
        @Override
        public void buyIt() {
            System.out.println("This computer is from HangKang!");
        }
    }
    //代理对象角色
    class ProxyMacBook implements IMacBook {
        @Override
        public void buyIt() {
            HangKangMacBook mac = new HangKangMacBook();
            mac.buyIt();
        }
    }
    //客户端
    public class Main {
        public static void main(String[] args) {
            IMacBook macBook = new ProxyMacBook();
            macBook.buyIt();
        }
    }

    在Android中的一个代理模式运用实例:

    在Android中代理模式也是使用广泛的,例如ActivityManagerProxy类就是一个代理,它是ActivityManagerNative的代理,也就是说ActivityManagerProxy是上面所说的Proxy类,而ActivityManagerNative就相当于RealSubject类,它们都有一个共有的接口IActivityManager。在这里还有一个重要的类:ActivityManager,它相当于代理模式的类图中的client。在这个类中,可以看到大量的getxxx函数,这些函数,都会调用到ActivityManagerNative类的getDefault()方法,而该方法会获得一个共用的单例的IActivityManager引用,然后通过多态来调用代理中的实现。

    总结一把

    代理模式优点:

    • 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
    • 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性。
    • 远程代理为位于两个不同地址空间对象的访问提供了一种实现机制,可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高系统的整体运行效率。
    • 虚拟代理通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销。
    • 缓冲代理为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,优化系统性能,缩短执行时间。
    • 保护代理可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限。

    代理模式缺点:

    • 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。
    • 实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理。

    【工匠若水 http://blog.csdn.net/yanbober】 继续阅读《设计模式(行为型)之观察者模式(Observer Pattern)》http://blog.csdn.net/yanbober/article/details/45484749

    展开全文
  • 面向对象六大原则——接口隔离原则

    万次阅读 多人点赞 2018-08-13 10:54:15
    什么是接口隔离原则...在讲接口隔离原则之前,先说说接口,接口分为以下两种: - 实例接口(Object Interface): 在Java中声明一个类,然后用new关键字产生一个实例,是对一个类型的事物的描述,这就是一种接口...
    
    

    什么是接口隔离原则(Interface Segregation Principle, ISP)

     接口对于Java开发者来说都不陌生,它几乎存在于每一个Java程序中,是抽象的代名词。在讲接口隔离原则之前,先说说接口,接口分为以下两种:

    • 实例接口(Object Interface): 在Java中声明一个类,然后用new关键字产生一个实例,是对一个类型的事物的描述,这就是一种接口。或许我们乍一看会有点懵,怎么和我们原来学习的接口不一样呢,其实我们这样想,我们都知道,在Java中有一个Class类,表示正在运行的类和接口,换句话说每一个正在运行时的类或接口都是Class类的对象,这是一种向上的抽象。接口是一种更为抽象的定义,类是一类相同事物的描述集合,那为什么不可以抽象为一个接口呢?
    • 类接口(Class Interface): 这就是我们经常使用的用interface定义的接口

     这里插一句,接口隔离原则中所说的接口并不是狭意的在Java中用interface定义的接口,而是一种更为宽泛的概念,可以是接口,抽象类或者实体类。

    接口隔离原则定义如下:

    • 客户端不应该依赖它不需要的接口
    • 类间的依赖关系应该建立在最小的接口上

     其实通俗来理解就是,不要在一个接口里面放很多的方法,这样会显得这个类很臃肿不堪。接口应该尽量细化,一个接口对应一个功能模块,同时接口里面的方法应该尽可能的少,使接口更加轻便灵活。或许看到接口隔离原则这样的定义很多人会觉得和单一职责原则很像,但是这两个原则还是有着很鲜明的区别。接口隔离原则和单一职责原则的审视角度是不同的,单一职责原则要求类和接口职责单一,注重的是职责,是业务逻辑上的划分,而接口隔离原则要求方法要尽可能的少,是在接口设计上的考虑。例如一个接口的职责包含10个方法,这10个方法都放在一个接口中,并且提供给多个模块访问,各个模块按照规定的权限来访问,并规定了“不使用的方法不能访问”,这样的设计是不符合接口隔离原则的,接口隔离原则要求“尽量使用多个专门的接口”,这里专门的接口就是指提供给每个模块的都应该是单一接口(即每一个模块对应一个接口),而不是建立一个庞大臃肿的接口来容纳所有的客户端访问。

    接口隔离原则的使用

     在说接口隔离原则之前,我们先说一个没有使用该原则的例子,然后通过前后对比,来看看有什么不同之处。大家一听到“美女”这个字眼,会想到什么呢?别激动啊,我没啥意思,只是想给美女来定一个通用的标准:面貌,身材与气质,一般来说,长得好看的,身材不错的,气质出众的都可以称为美女。假如我现在是一个星探,下面我要设计一个找美女的类图:

     定义了一个IPettyGirl接口,声明所有的美女都应该有goodLooking,niceFigure,greatTemperament。还定义了一个抽象类AbstractSearcher,其作用就是搜索美女并显示其信息。下面是接口的定义与实现:

    //美女接口
    public interface IPettyGirl {
        //要有姣好的面孔
        public void goodLooking();
        //要有好身材
        public void niceFigure();
        //要有气质
        public void greatTemperament();
    }
    
    //接口的实现类
    public class PettyGirl implements IPettyGirl {
        private String name;
    
        public PettyGirl(String  name){
           this.name= name;
    }
    
    //脸蛋漂亮
    public void goodLooking() {
         System.out.println(this.name + "---脸蛋很漂亮!");
    }
    
    //气质要好
    public void greatTemperament() {
          System.out.println(this.name + "---气质非常好!");
    }
    
    //身材要好
    public void niceFigure() {
          System.out.println(this.name + "---身材非常棒!");
       }
    }
    

    美女有了,就需要星探出马找美女了:

    //星探的抽象
    public abstract class AbstractSearcher {
    
        protected IPettyGirl pettyGirl;
    
        public AbstractSearcher(IPettyGirl pettyGirl){
            this.pettyGirl = pettyGirl;
       }
         //搜索美女, 列出美女信息
        public abstract void show();
    }
    
    //实现类
    public class Searcher extends AbstractSearcher{
    
         public Searcher(IPettyGirl pettyGirl){
             super(pettyGirl);
       }
    
        //展示美女的信息
        public void show(){
            System.out.println("--------美女的信息如下: ---------------");
             //展示面容
            super.pettyGirl.goodLooking();
             //展示身材
            super.pettyGirl.niceFigure();
            //展示气质
            super.pettyGirl.greatTemperament();
          }
    }
    
    //下面是客户端代码
    public class Client {
          //搜索并展示美女信息
          public static void main(String[] args) {
          //定义一个美女
          IPettyGirl xiaoMei = new PettyGirl("小美");
          AbstractSearcher searcher = new Searcher(yanYan);
          searcher.show();
        }
    }
    

     OK,找美女的过程开发完毕,总体来说还是不错的,因为只要按照我们设计的原则来,那么找到的都是美女。但是这样的设计是最优的吗?现在考虑这样一种情况,由于人们审美的提高,或许颜值不一定是我们关注的主要因素,也许某个女生虽然颜值不是太高,但是气质很好,也可以把她称为美女。也有可能某些人喜欢身材匀称的,有的人觉得骨感一点好。也就是是说,美女的定义是可以宽泛话的,并非一成不变的。就如同我们的设计,必须符合我们定好的原则那才是美女,显然这是说不通的。所以上面的设计是有问题的,显然IPrettyGirl这个接口过于庞大了,根据接口隔离原则,星探AbstractSearcher应该依赖于具有部分特质的女孩子,但上面的设计却把这些特质都封装起来,放到一个接口中,这样就造成了封装过度,不容易扩展。


     现在我们找到了问题的原因,那就该接口隔离原则上场了。把原IPrettyGirl接口拆分为两个接口,一种是外形美女IGoodBodyGirl(相貌一流,身材不错,但气质可能差点),另一种是气质美女IGreatTemperamentGirl(也许外形条件不出众,但是谈吐优雅得体,气质很好)。下面是设计类图:

    public interface IGoodBodyGirl {
         //要有姣好的面孔
         public void goodLooking();
         //要有好身材
         public void niceFigure();
    }
    
    public interface IGreatTemperamentGirl {
        //要有气质
        public void greatTemperament();
    }
    
    public class PettyGirl implements IGoodBodyGirl,IGreatTemperamentGirl {
         private String name;
    
         public PettyGirl(String _name){
            this.name=_name;
      }
    
        //脸蛋漂亮
        public void goodLooking() {
            System.out.println(this.name + "---脸蛋很漂亮!");
       }
    
        //气质要好
        public void greatTemperament() {
           System.out.println(this.name + "---气质非常好!");
       }
    
       //身材要好
       public void niceFigure() {
            System.out.println(this.name + "---身材非常棒!");
       }
    }
    

    OK,现在经过重新设计,程序变得更加灵活,这就是接口隔离原则的强大之处。

    ISP的几个使用原则

    • 根据接口隔离原则拆分接口时,首先必须满足单一职责原则: 没有哪个设计可以十全十美的考虑到所有的设计原则,有些设计原则之间就可能出现冲突,就如同单一职责原则和接口隔离原则,一个考虑的是接口的职责的单一性,一个考虑的是方法设计的专业性(尽可能的少),必然是会出现冲突。在出现冲突时,尽量以单一职责为主,当然这也要考虑具体的情况。
    • 提高高内聚: 提高接口,类,模块的处理能力,减少对外的交互。比如你给杀手提交了一个订单,要求他在一周之内杀一个人,一周后杀手完成了任务,这种不讲条件完成任务的表现就是高内聚。具体来说就是:要求在接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险就越小,也有利于降低成本。
    • 定制服务: 单独为一个个体提供优良服务(只提供访问者需要的方法)。
    • 接口设计要有限度: 根据经验判断

    参考书籍

    • 《设计模式之禅》
    展开全文
  • 设计模式(六)代理模式

    万次阅读 2016-03-19 15:19:52
    设计模式(一)设计六大原则 设计模式(二)单例模式的七种写法 设计模式(三)建造者模式 设计模式(四)简单工厂模式 设计模式(五)观察者模式 1.代理模式简介 代理模式介绍 代理...

    相关文章
    设计模式(一)设计六大原则
    设计模式(二)单例模式的七种写法
    设计模式(三)建造者模式
    设计模式(四)简单工厂模式
    设计模式(五)观察者模式

    1.代理模式简介

    代理模式介绍

    代理模式也叫委托模式,是结构型设计模式的一种。在现实生活中我们用到类似代理模式的场景有很多,比如代购、代理上网、打官司等。

    定义

    为其他对象提供一种代理以控制这个对象的访问。

    代理模式结构图

    这里写图片描述

    • Subject:抽象主题类,声明真实主题与代理的共同接口方法。
    • RealSubject:真实主题类,定义了代理所表示的真实对象,客户端通过代理类间接的调用真实主题类的方法。
    • ProxySubject:代理类,持有对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行。
    • Client:客户端类。

    2.代理模式的简单实现

    假设我要买一个BV的包(博主我很喜欢一直买不起),国内的太贵了,我找了个代购来帮我海外购买,这样能省好多钱,哈哈。

    抽象主题类(Subject)

    抽象主题类具有真实主题类和代理的共同接口方法,我想要代购,那共同的方法就是购买:

    public interface IShop {
        //购买
        void buy();
    }

    真实主题类(RealSubject)

    这个购买者LiuWangShu也就是我,实现了IShop接口提供的 buy()方法:

    public class LiuWangShu implements IShop {
        @Override
        public void buy() {
            System.out.println("购买");
        }
    }

    代理类(ProxySubject)

    我找的代理类同样也要实现IShop接口,并且要持有被代理者,在buy()方法中调用了被代理者的buy()方法:

    public class Purchasing implements IShop {
        private IShop mShop;
        public Purchasing(IShop shop){
            mShop=shop;
        }
    
        @Override
        public void buy() {
            mShop.buy();
        }
    }

    客户端类(Client)

    public class Client {
        public static void main(String[] args){
            //创建LiuWangShu
            IShop liuwangshu=new LiuWangShu();
            //创建代购者并将LiuWangShu作为构造函数传
            IShop purchasing=new Purchasing(liuwangshu);
            purchasing.buy();
        }
    }

    看完客户端类的代码,其实也是很好理解,就是代理类包含了真实主题类(被代理者),最终调用的都是真实主题类(被代理者)实现的方法,在上面的例子就是LiuWangShu类的buy()方法,所以运行的结果就是“购买”。

    3.动态代理的简单实现

    从编码的角度来说,代理模式分为静态代理和动态代理,上面的例子是静态代理,在代码运行前就已经存在了代理类的class编译文件,而动态代理则是在代码运行时通过反射来动态的生成代理类的对象,并确定到底来代理谁。也就是我们在编码阶段不需要知道代理谁,代理谁我们将会在代码运行时决定。Java提供了动态的代理接口InvocationHandler,实现该接口需要重写invoke()方法。下面我们在上面静态代理的例子上做修改:

    创建动态代理类:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class DynamicPurchasing implements InvocationHandler{
        private Object obj;
        public DynamicPurchasing(Object obj){
            this.obj=obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result=method.invoke(obj, args);
            return result;
        }
    }

    在动态代理类中我们声明一个Object的引用,该引用指向被代理类,我们调用被代理类的具体方法在invoke()方法中执行。接下来我们修改客户端类代码:

    import java.lang.reflect.Proxy;
    public class Client {
        public static void main(String[] args){
            //创建LiuWangShu
            IShop liuwangshu=new LiuWangShu();
            //创建动态代理
            DynamicPurchasing  mDynamicPurchasing=new DynamicPurchasing(liuwangshu);
            //创建LiuWangShu的ClassLoader
            ClassLoader loader=liuwangshu.getClass().getClassLoader();
            //动态创建代理类
            IShop purchasing= (IShop) Proxy.newProxyInstance(loader,new Class[]{IShop.class},mDynamicPurchasing);
            purchasing.buy();
        }
    }
    

    4.代理模式的应用

    代理模式类型

    代理模式的类型主要有以下几点:

    1. 远程代理:为一个对象在不同的地址空间提供局部代表,这样系统可以将Server部分的事项隐藏。
    2. 虚拟代理:使用一个代理对象表示一个十分耗资源的对象并在真正需要时才创建。
    3. 安全代理:用来控制真实对象访问时的权限。
    4. 智能指引:当调用真实的对象时,代理处理另外一些事,比如计算真实对象的引用计数,当该对象没有引用时,可以自动释放它;或者访问一个实际对象时,检查是否已经能够锁定它,以确保其他对象不能改变它。

    代理模式使用场景

    无法或者不想直接访问某个对象时可以通过一个代理对象来间接的访问。

    展开全文
  • 面向对象的原则之单一职责原则

    千次阅读 2016-09-21 08:27:15
    单一职责原则(Single Responsibility Principle, SRP): 一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。  亚当·斯密曾就制针业做过一个分工产生效率的...
  • Java代理模式及其应用

    万次阅读 多人点赞 2017-07-03 16:01:17
    代理根据代理类的产生方式和时机分为静态代理和动态代理两种。代理类不仅可以有效的将具体的实现与调用方进行解耦,通过面向接口进行编码完全将具体的实现隐藏在内部,而且还可以在符合开闭原则的前提下,对目标类...
  • 面向对象设计原则之里氏代换原则

    万次阅读 多人点赞 2012-05-06 21:56:23
    里氏代换原则由2008年图灵奖得主、美国第一计算机科学女博士Barbara Liskov教授和卡内基·梅隆大学Jeannette Wing教授于1994年提出。其严格表述如下:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T...
  • 1. 设计模式三大分类 设计模式分为三种类型,共23类。(1)创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。(2)结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式...
  • 常见的国内最新代理ip有哪些

    千次阅读 2021-03-02 17:13:37
    市场上代理ip的种类很多,按照不同的方式,可以分为多种类型。其中包括HTTP(s)代理ip,socks5代理ip,动态代理ip,静态代理ip,独占ip池和共享ip池。很难确定哪个更好,因为每个人的业务场景不同,对代理ip的需求也...
  • 深入理解代理模式:静态代理与JDK动态代理

    万次阅读 多人点赞 2018-03-01 00:22:11
    根据代理类的创建时机和创建方式的不同,可以将其分为静态代理和动态代理两种形式:在程序运行前就已经存在的编译好的代理类是为静态代理,在程序运行期间根据需要动态创建代理类及其实例来完成具体的功能是为动态...
  • java动态代理实现与原理详细分析

    千次阅读 多人点赞 2019-02-08 23:22:43
    一、代理 (1)、什么是代理? 大道理上讲代理是一种软件设计模式,目的地希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法...设计模式中有一个设计原则是开...
  • 系统设计原则

    千次阅读 2018-10-03 20:27:35
    高并发原则 高可用原则 业务设计原则 高并发原则 1. 无状态 若应用无状态、方便水平扩展、则要保证配置服务有状态 eg. 不同的机房需要读取不同的数据源、此时可以通过配置中心指定 2. 拆分 拆分不是必须的、...
  • MySQL 索引最左匹配原则

    千次阅读 2016-10-24 22:11:58
    这同样也是覆盖索引,但是对过滤没什么帮助(记住MySQL索引的最左原则)。 多个等于查询(Multiple equalities) [sql]   view plain   copy SELECT  *  FROM  t  WHERE  c = 100  and  d =  'xyz'   ...
  • (1)设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑,这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强。...
  • java动态代理:JDK接口实现方式

    千次阅读 2018-06-11 11:26:21
    (1)什么是代理?大道理上讲代理是一种软件设计模式,目的地希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的...(1)设计模式中有一个设计原则是开闭原则,是说...
  • 代理模式:女朋友这么漂亮,你缺经纪人吗?

    千次阅读 多人点赞 2016-08-20 23:46:23
    //王宝强,一可爱、淳朴的明星,最早看的是他的《天下无贼》和《盲井》 Star baoqiang = new Star( "王宝强" ); //有个经纪人叫宋吉吉 Agent songJJ = new Agent(baoqiang, false ); songJJ....
  • Restful API 设计原则

    千次阅读 2018-04-10 05:00:11
    Restful API 设计原则 前言 网络应用程序分为前端和后端两个部分。 当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备……),这也就意味着前端的开发代码、开发框架变得多种多样。...
  • 设计模式及各大原则简介

    千次阅读 2014-05-15 17:36:26
    定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。 定义2:所有引用...
  • 设计模式六大原则

    千次阅读 2017-05-15 16:30:19
    设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计模式六大原则...
  • 动态代理与静态代理区别

    万次阅读 多人点赞 2018-09-18 09:26:55
    根据代理类的生成时间不同可以将代理分为静态代理和动态代理两种。  下面以一个模拟需求说明静态代理和动态代理:委托类要处理一项耗时较长的任务,客户类需要打印出执行任务消耗的时间。解决这个问题需要记录...
  • 本文介绍了设计模式的基本分类、通过案例的方式介绍面向对象的 6 大设计原则,最后通过项目案例分析如何使用面向对象的设计原则
  • 系统设计六大原则

    千次阅读 2019-05-30 23:08:33
    SOLID 原则: S 单一职责原则 单一责任,一个类只负责一个职责。(single responsiblity) O 开闭原则 对继承和发展开放,对修改关闭。(open and close) L 里式替换原则 子类可是替换父类 (Liskov substituation ...
  • 根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理、远程代理、虚拟代理、缓冲代理等,它们应用于不同的场合,满足用户的不同需求。 1 代理模式概述 近年来,代购已逐步成为电
  • 设计模式分类以及六大原则

    千次阅读 2016-06-26 23:38:52
    设计模式的分类总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、...
  • 原则-开闭原则 对扩展开放,对修改封闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。 想要达到...
  • 代理模式分为四类:远程代理,虚代理,保护代理和智能引用。
  • 23种设计模式及6大原则

    千次阅读 2017-06-04 16:34:08
    23种设计模式及6大原则一.设计模式分类总体来说设计模式分为三大类: 创建型模式 工厂方法模式 抽象工厂模式 单例模式 建造者模式 原型模式 结构型模式 适配器模式 装饰器模式 代理模式 外观模式 桥接模式...
  • 浅谈设计模式的六大原则

    千次阅读 2016-05-26 21:48:28
    一,单一职责原则:就一个类而言,应该仅有一个引起它变化的原因(就是实现类要责任单一) 英文--Single Responsibility Principle  简写:SRP 举个例子:  父类:Animal public class Animal { void move...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 68,866
精华内容 27,546
关键字:

代位原则分为