精华内容
下载资源
问答
  • 2022-03-30 10:59:04

    安卓11及以上不用电脑永久激活冰箱
    #iQOONeo5活力版# #冰箱icebox#
    i#iQOO#
    众所周知,蓝厂解bl难如登天,所以优化大部分建立在adb命令上

    安卓11可以使用黑域的无线调试功能激活应该都知道,激活黑域后,

    如果已经有冰箱,卸载重新安装冰箱
    1.卸载支付宝
    2.在设置-账号与同步里删除所有账号,关闭自动同步功能,退出vivo账号
    3.点击黑域左上角-执行指令
    pm remove-user 999
    4.点击黑域左上角-执行指令
    dpm set-device-owner com.catchingnow.icebox/.receiver.DPMReceiver
    5.至此over

    更多相关内容
  • Android常用命令行指令

    2022-02-26 11:39:12
    Android 在Cmd下指令 管理设备 adb devices 显示连接到计算机的设备 adb get-serialno 获取设备的ID和序列号serialNumber adb reboot 重启设备 adb reboot bootloader 重启到bootloader...
    Android
    在Cmd下指令
    管理设备adb devices显示连接到计算机的设备
    adb get-serialno获取设备的ID和序列号serialNumber
    adb reboot重启设备
    adb reboot bootloader重启到bootloader,即刷机模式
    adb reboot recovery重启到recovery,即恢复模式
    adb [-d|-e|-s <serialNumber>] <command>
    -d 发送命令给usb连接的设备
    -e 发送命令到模拟器设备
    -s <serialNumber> 发送命令到指定设备
    adb相关adb kill-server终止adb服务进程
    adb start-server重启adb服务进程
    adb root已root权限重启adb服务
    adb wait-for-device在模拟器/设备连接之前把命令转载在adb的命令器中
    获取设备硬件信息adb shell  cat /sys/class/net/wlan0/address获取mac地址
    adb shell cat /proc/cpuinf获取cpu序列号
    管理设备appaapt d badging <apkfile>获取apk的packagename 和 classname
    adb install <apkfile>安装apk
    adb install -r <apkfile>保留数据和缓存文件,重新安装apk
    adb install -s <apkfile> 安装apk到sd卡
    adb uninstall <package>卸载app
    adb uninstall -k <package>卸载app但保留数据和缓存文件
    shellam start -n <package_name>/.<activity_class_name>启动应用
    top查看设备cpu和内存占用情况
    top -m 6查看占用内存前6的app
    top -n 1刷新一次内存信息,然后返回
    procrank查询各进程内存使用情况
    kill [pid]杀死一个进程
    ps查看进程列表
    ps -x [PID]查看指定进程状态
    service list查看后台services信息
    cat /proc/meminfo查看当前内存占用
    cat /proc/iomem查看IO内存分区
    ls列出目录下的文件和文件夹,等同于dos中的dir命令
    cd进入文件夹,等同于dos中的cd 命令
    rename重命名文件
    rm删除
    mv移动文件
    chmod设置文件权限
    mkdir新建文件夹
    cat查看文件内容
    su获取管理员权限
    文件操作adb remount将system分区重新挂载为可读写分区
    adb pull <remote> <local>获取模拟器中的文件
    adb push <local> <remote>向模拟器中写文件
    其他android list targets显示系统中全部Android平台
    android list avd显示系统中全部AVD(模拟器)
    android create avd -name 名称 -target 平台编号创建AVD模拟器
    emulator -avd 名称 -sdcard ~/名称.img(-skin 1280x800)启动模拟器
    android delete avd -name 名称删除AVD(模拟器)
    mksdcard 1024M ~/名称.img创建SDCard
    ddms启动DDMS
    adb devices显示当前运行的全部模拟器
    adb -s 模拟器编号 命令对某一模拟器执行命令
    adb shell进入模拟器的shell模拟
    android启动SDK,文档,实例下载管理器
    adb uninstall apk包的主包名卸载apk包
    adb help查看adb命令帮助信息
    adb logcat -s 标签名在命令行中查看log信息
    源码\system\core\toolbox目录和源码\frameworks\base\cmds目录adb shell后面跟的命令主要来自
    adb remount (重新挂载系统分区,使系统分区重新可写)。    adb shell    cd system/app    rm *.apk删除系统应用
    adb root获取管理员权限
    你可以设置任意的端口号,做为主机向模拟器或设备的请求端口。    如:adb forward tcp:5555 tcp:8000发布端口
    你可向一个设备或从一个设备中复制文件,    复制一个文件或目录到设备或模拟器上:    adb push <source> <destination></destination></source>    如:adb push test.txt /tmp/test.txt    从设备或模拟器上复制一个文件或目录:    adb pull <source> <destination></destination></source>    如:adb pull /addroid/lib/libwebcore.so复制文件
    取得当前运行的模拟器/设备的实例的列表及每个实例的状态:    adb devices搜索模拟器/设备的实例
    adb bugreport查看bug报告
     一般来说,无线通讯的日志非常多,在运行时没必要去记录,但我们还是可以通过命令,设置记录:    adb shell    logcat -b radio记录无线通讯日志
    adb get-product    adb get-serialno获取设备的ID和序列号
    adb shell    sqlite3    #cd system/sd/data //进入系统内指定文件夹    #ls //列表显示当前文件夹内容    #rm -r xxx //删除名字为xxx的文件夹及其里面的所有文件    #rm xxx //删除文件xxx     #rmdir xxx //删除xxx的文件夹访问数据库SQLite3
    展开全文
  • Android 23种设计模式全面解析

    千次阅读 2020-06-23 20:48:50
    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 其实还有两类:并发型模式和线程池模式。用一个图片...

    一、设计模式的分类


    总体来说设计模式分为三大类:

    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下:

     

    二、设计模式的六大原则


    总原则:开闭原则(Open Close Principle)

    开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。

    1、单一职责原则

    不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。

     

    2、里氏替换原则(Liskov Substitution Principle)

    里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科

    历史替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。

     

    3、依赖倒转原则(Dependence Inversion Principle)

    这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

     

    4、接口隔离原则(Interface Segregation Principle)

    这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

     

    5、迪米特法则(最少知道原则)(Demeter Principle)

    就是说:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

    最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。

     

    6、合成复用原则(Composite Reuse Principle)

    原则是尽量首先使用合成/聚合的方式,而不是使用继承。

     

    三、Java的23中设计模式


    A、创建模式

    从这一块开始,我们详细介绍Java中23种设计模式的概念,应用场景等情况,并结合他们的特点及设计模式的原则进行分析。

     

    首先,简单工厂模式不属于23中涉及模式,简单工厂一般分为:普通简单工厂、多方法简单工厂、静态方法简单工厂。

    0、简单工厂模式

    简单工厂模式模式分为三种:

    01、普通

    就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图:

    举例如下:(我们举一个发送邮件和短信的例子)

    首先,创建二者的共同接口:

    view plaincopy

    public interface Sender {  
        public void Send();  
    }  

    其次,创建实现类:

    view plaincopy

    public class MailSender implements Sender {  
        @Override  
        public void Send() {  
            System.out.println("this is mailsender!");  
        }  
    }  

    view plaincopy

    public class SmsSender implements Sender {  
      
        @Override  
        public void Send() {  
            System.out.println("this is sms sender!");  
        }  
    }  

    最后,建工厂类:

    view plaincopy

    public class SendFactory {  
      
        public Sender produce(String type) {  
            if ("mail".equals(type)) {  
                return new MailSender();  
            } else if ("sms".equals(type)) {  
                return new SmsSender();  
            } else {  
                System.out.println("请输入正确的类型!");  
                return null;  
            }  
        }  
    }  

    我们来测试下:

    public class FactoryTest {  
      
        public static void main(String[] args) {  
            SendFactory factory = new SendFactory();  
            Sender sender = factory.produce("sms");  
            sender.Send();  
        }  
    }  

    输出:this is sms sender!

    02、多个方法

    是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。关系图:

    将上面的代码做下修改,改动下SendFactory类就行,如下:

    view plaincopy

    public class SendFactory {  
    
       public Sender produceMail(){  
    
            return new MailSender();  
        }  
          
        public Sender produceSms(){  
            return new SmsSender();  
        }  
    }  

    测试类如下:

    view plaincopy

    public class FactoryTest {  
      
        public static void main(String[] args) {  
            SendFactory factory = new SendFactory();  
            Sender sender = factory.produceMail();  
            sender.Send();  
        }  
    }  

    输出:this is mailsender!

    03、多个静态方法

    将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    view plaincopy

    public class SendFactory {  
          
        public static Sender produceMail(){  
            return new MailSender();  
        }  
          
        public static Sender produceSms(){  
            return new SmsSender();  
        }  
    }  

    view plaincopy

    public class FactoryTest {  
      
        public static void main(String[] args) {      
            Sender sender = SendFactory.produceMail();  
            sender.Send();  
        }  
    }  

    输出:this is mailsender!

    总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

    1、工厂方法模式(Factory Method)


    简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

    请看例子:

    view plaincopy

    public interface Sender {  
        public void Send();  
    }  

    两个实现类:

    view plaincopy

    public class MailSender implements Sender {  
        @Override  
        public void Send() {  
            System.out.println("this is mailsender!");  
        }  
    }  

    view plaincopy

    public class SmsSender implements Sender {  
      
        @Override  
        public void Send() {  
            System.out.println("this is sms sender!");  
        }  
    }  

    两个工厂类:

    view plaincopy

    public class SendMailFactory implements Provider {  
          
        @Override  
        public Sender produce(){  
            return new MailSender();  
        }  
    }  

    view plaincopy

    public class SendSmsFactory implements Provider{  
      
        @Override  
        public Sender produce() {  
            return new SmsSender();  
        }  
    }  

    在提供一个接口:

    view plaincopy

    public interface Provider {  
        public Sender produce();  
    }  

    测试类:

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
            Provider provider = new SendMailFactory();  
            Sender sender = provider.produce();  
            sender.Send();  
        }  
    }  

    其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!

     

    2、抽象工厂模式


    工厂方法模式和抽象工厂模式不好分清楚,他们的区别如下:

    工厂方法模式:
    一个抽象产品类,可以派生出多个具体产品类。   
    一个抽象工厂类,可以派生出多个具体工厂类。   
    每个具体工厂类只能创建一个具体产品类的实例。
    
    抽象工厂模式:
    多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   
    一个抽象工厂类,可以派生出多个具体工厂类。   
    每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品。   
        
    区别:
    工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。   
    工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
    工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。 
    
    抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承。
    
    对于java来说,你能见到的大部分抽象工厂模式都是这样的:
    ---它的里面是一堆工厂方法,每个工厂方法返回某种类型的对象。
    
    比如说工厂可以生产鼠标和键盘。那么抽象工厂的实现类(它的某个具体子类)的对象都可以生产鼠标和键盘,但可能工厂A生产的是罗技的键盘和鼠标,工厂B是微软的。
    
    这样A和B就是工厂,对应于抽象工厂;
    每个工厂生产的鼠标和键盘就是产品,对应于工厂方法;
    
    用了工厂方法模式,你替换生成键盘的工厂方法,就可以把键盘从罗技换到微软。但是用了抽象工厂模式,你只要换家工厂,就可以同时替换鼠标和键盘一套。如果你要的产品有几十个,当然用抽象工厂模式一次替换全部最方便(这个工厂会替你用相应的工厂方法)
    
    所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线
    

    3、单例模式(Singleton


    单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:

    1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

    2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

    3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。

    首先我们写一个简单的单例类:

    view plaincopy

    public class Singleton {  
      
        /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */  
        private static Singleton instance = null;  
      
        /* 私有构造方法,防止被实例化 */  
        private Singleton() {  
        }  
      
        /* 静态工程方法,创建实例 */  
        public static Singleton getInstance() {  
            if (instance == null) {  
                instance = new Singleton();  
            }  
            return instance;  
        }  
      
        /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */  
        public Object readResolve() {  
            return instance;  
        }  
    }  


    这个类可以满足基本要求,但是,像这样毫无线程安全保护的类,如果我们把它放入多线程的环境下,肯定就会出现问题了,如何解决?我们首先会想到对getInstance方法加synchronized关键字,如下:

    view plaincopy

    public static synchronized Singleton getInstance() {  
            if (instance == null) {  
                instance = new Singleton();  
            }  
            return instance;  
        }  

    但是,synchronized关键字锁住的是这个对象,这样的用法,在性能上会有所下降,因为每次调用getInstance(),都要对对象上锁,事实上,只有在第一次创建对象的时候需要加锁,之后就不需要了,所以,这个地方需要改进。我们改成下面这个:

    view plaincopy

    public static Singleton getInstance() {  
            if (instance == null) {  
                synchronized (instance) {  
                    if (instance == null) {  
                        instance = new Singleton();  
                    }  
                }  
            }  
            return instance;  
        }  

    似乎解决了之前提到的问题,将synchronized关键字加在了内部,也就是说当调用的时候是不需要加锁的,只有在instance为null,并创建对象的时候才需要加锁,性能有一定的提升。但是,这样的情况,还是有可能有问题的,看下面的情况:在Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就可能出错了,我们以A、B两个线程为例:

    a>A、B线程同时进入了第一个if判断

    b>A首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();

    c>由于JVM内部的优化机制,JVM先画出了一些分配给Singleton实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块。

    d>B进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序。

    e>此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。

    所以程序还是有可能发生错误,其实程序在运行过程是很复杂的,从这点我们就可以看出,尤其是在写多线程环境下的程序更有难度,有挑战性。我们对该程序做进一步优化:

    view plaincopy

    private static class SingletonFactory{           
            private static Singleton instance = new Singleton();           
        }           
        public static Singleton getInstance(){           
            return SingletonFactory.instance;           
        }   

    实际情况是,单例模式使用内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕,这样我们就不用担心上面的问题。同时该方法也只会在第一次调用的时候使用互斥机制,这样就解决了低性能问题。这样我们暂时总结一个完美的单例模式:

    view plaincopy

    public class Singleton {  
      
        /* 私有构造方法,防止被实例化 */  
        private Singleton() {  
        }  
      
        /* 此处使用一个内部类来维护单例 */  
        private static class SingletonFactory {  
            private static Singleton instance = new Singleton();  
        }  
      
        /* 获取实例 */  
        public static Singleton getInstance() {  
            return SingletonFactory.instance;  
        }  
      
        /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */  
        public Object readResolve() {  
            return getInstance();  
        }  
    }  

    其实说它完美,也不一定,如果在构造函数中抛出异常,实例将永远得不到创建,也会出错。所以说,十分完美的东西是没有的,我们只能根据实际情况,选择最适合自己应用场景的实现方法。也有人这样实现:因为我们只需要在创建类的时候进行同步,所以只要将创建和getInstance()分开,单独为创建加synchronized关键字,也是可以的:

    view plaincopy

    public class SingletonTest {  
      
        private static SingletonTest instance = null;  
      
        private SingletonTest() {  
        }  
      
        private static synchronized void syncInit() {  
            if (instance == null) {  
                instance = new SingletonTest();  
            }  
        }  
      
        public static SingletonTest getInstance() {  
            if (instance == null) {  
                syncInit();  
            }  
            return instance;  
        }  
    }  

    考虑性能的话,整个程序只需创建一次实例,所以性能也不会有什么影响。

    补充:采用"影子实例"的办法为单例对象的属性同步更新

    view plaincopy

    public class SingletonTest {  
      
        private static SingletonTest instance = null;  
        private Vector properties = null;  
      
        public Vector getProperties() {  
            return properties;  
        }  
      
        private SingletonTest() {  
        }  
      
        private static synchronized void syncInit() {  
            if (instance == null) {  
                instance = new SingletonTest();  
            }  
        }  
      
        public static SingletonTest getInstance() {  
            if (instance == null) {  
                syncInit();  
            }  
            return instance;  
        }  
      
        public void updateProperties() {  
            SingletonTest shadow = new SingletonTest();  
            properties = shadow.getProperties();  
        }  
    }  

    通过单例模式的学习告诉我们:

    1、单例模式理解起来简单,但是具体实现起来还是有一定的难度。

    2、synchronized关键字锁定的是对象,在用的时候,一定要在恰当的地方使用(注意需要使用锁的对象和过程,可能有的时候并不是整个对象及整个过程都需要锁)。

    到这儿,单例模式基本已经讲完了,结尾处,笔者突然想到另一个问题,就是采用类的静态方法,实现单例模式的效果,也是可行的,此处二者有什么不同?

    首先,静态类不能实现接口。(从类的角度说是可以的,但是那样就破坏了静态了。因为接口中不允许有static修饰的方法,所以即使实现了也是非静态的)

    其次,单例可以被延迟初始化,静态类一般在第一次加载是初始化。之所以延迟加载,是因为有些类比较庞大,所以延迟加载有助于提升性能。

    再次,单例类可以被继承,他的方法可以被覆写。但是静态类内部方法都是static,无法被覆写。

    最后一点,单例类比较灵活,毕竟从实现上只是一个普通的Java类,只要满足单例的基本需求,你可以在里面随心所欲的实现一些其它功能,但是静态类不行。从上面这些概括中,基本可以看出二者的区别,但是,从另一方面讲,我们上面最后实现的那个单例模式,内部就是用一个静态类来实现的,所以,二者有很大的关联,只是我们考虑问题的层面不同罢了。两种思想的结合,才能造就出完美的解决方案,就像HashMap采用数组+链表来实现一样,其实生活中很多事情都是这样,单用不同的方法来处理问题,总是有优点也有缺点,最完美的方法是,结合各个方法的优点,才能最好的解决问题!

     

    4、建造者模式(Builder)


    5、原型模式(Prototype)


    原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。本小结会通过对象的复制,进行讲解。在Java中,复制对象是通过clone()实现的,先创建一个原型类:

    view plaincopy

    public class Prototype implements Cloneable {  
      
        public Object clone() throws CloneNotSupportedException {  
            Prototype proto = (Prototype) super.clone();  
            return proto;  
        }  
    }  

    很简单,一个原型类,只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB,因为此处的重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的,具体怎么实现,我会在另一篇文章中,关于解读Java中本地方法的调用,此处不再深究。在这儿,我将结合对象的浅复制和深复制来说一下,首先需要了解对象深、浅复制的概念:

    浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

    深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。

    此处,写一个深浅复制的例子:

    view plaincopy

    public class Prototype implements Cloneable, Serializable {  
      
        private static final long serialVersionUID = 1L;  
        private String string;  
      
        private SerializableObject obj;  
      
        /* 浅复制 */  
        public Object clone() throws CloneNotSupportedException {  
            Prototype proto = (Prototype) super.clone();  
            return proto;  
        }  
      
        /* 深复制 */  
        public Object deepClone() throws IOException, ClassNotFoundException {  
      
            /* 写入当前对象的二进制流 */  
            ByteArrayOutputStream bos = new ByteArrayOutputStream();  
            ObjectOutputStream oos = new ObjectOutputStream(bos);  
            oos.writeObject(this);  
      
            /* 读出二进制流产生的新对象 */  
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
            ObjectInputStream ois = new ObjectInputStream(bis);  
            return ois.readObject();  
        }  
      
        public String getString() {  
            return string;  
        }  
      
        public void setString(String string) {  
            this.string = string;  
        }  
      
        public SerializableObject getObj() {  
            return obj;  
        }  
      
        public void setObj(SerializableObject obj) {  
            this.obj = obj;  
        }  
      
    }  
      
    class SerializableObject implements Serializable {  
        private static final long serialVersionUID = 1L;  
    }  

     

    要实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。

     

    B、结构模式(7种)


    我们接着讨论设计模式,上篇文章我讲完了5种创建型模式,这章开始,我将讲下7种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中对象的适配器模式是各种模式的起源,我们看下面的图:

     

    6、适配器模式


     适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

    01、类的适配器模式

    核心思想就是:有一个Source类,拥有一个方法,待适配,目标接口是Targetable,通过Adapter类,将Source的功能扩展到Targetable里,看代码:

    view plaincopy

    public class Source {  
      
        public void method1() {  
            System.out.println("this is original method!");  
        }  
    }  

    view plaincopy

    public interface Targetable {  
      
        /* 与原类中的方法相同 */  
        public void method1();  
      
        /* 新类的方法 */  
        public void method2();  
    }  

    view plaincopy

    public class Adapter extends Source implements Targetable {  
      
        @Override  
        public void method2() {  
            System.out.println("this is the targetable method!");  
        }  
    }  

    Adapter类继承Source类,实现Targetable接口,下面是测试类:

    view plaincopy

    public class AdapterTest {  
      
        public static void main(String[] args) {  
            Targetable target = new Adapter();  
            target.method1();  
            target.method2();  
        }  
    }  

    输出:

    this is original method!
    this is the targetable method!

    这样Targetable接口的实现类就具有了Source类的功能。

    02、对象的适配器模式

    基本思路和类的适配器模式相同,只是将Adapter类作修改,这次不继承Source类,而是持有Source类的实例,以达到解决兼容性的问题。看图:

     

    只需要修改Adapter类的源码即可:

    view plaincopy

    public class Wrapper implements Targetable {  
      
        private Source source;  
          
        public Wrapper(Source source){  
            super();  
            this.source = source;  
        }  
        @Override  
        public void method2() {  
            System.out.println("this is the targetable method!");  
        }  
      
        @Override  
        public void method1() {  
            source.method1();  
        }  
    }  

    测试类:

    view plaincopy

    public class AdapterTest {  
      
        public static void main(String[] args) {  
            Source source = new Source();  
            Targetable target = new Wrapper(source);  
            target.method1();  
            target.method2();  
        }  
    }  

    输出与第一种一样,只是适配的方法不同而已。

    03、接口的适配器模式

    第三种适配器模式是接口的适配器模式,接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。看一下类图:

    这个很好理解,在实际开发中,我们也常会遇到这种接口中定义了太多的方法,以致于有时我们在一些实现类中并不是都需要。看代码:

    view plaincopy

    public interface Sourceable {  
          
        public void method1();  
        public void method2();  
    }  

    抽象类Wrapper2:

    view plaincopy

    public abstract class Wrapper2 implements Sourceable{  
          
        public void method1(){}  
        public void method2(){}  
    }  

    view plaincopy

    public class SourceSub1 extends Wrapper2 {  
        public void method1(){  
            System.out.println("the sourceable interface's first Sub1!");  
        }  
    }  

    view plaincopy

    public class SourceSub2 extends Wrapper2 {  
        public void method2(){  
            System.out.println("the sourceable interface's second Sub2!");  
        }  
    }  

    view plaincopy

    public class WrapperTest {  
      
        public static void main(String[] args) {  
            Sourceable source1 = new SourceSub1();  
            Sourceable source2 = new SourceSub2();  
              
            source1.method1();  
            source1.method2();  
            source2.method1();  
            source2.method2();  
        }  
    }  

    测试输出:

    the sourceable interface's first Sub1!
    the sourceable interface's second Sub2!

    达到了我们的效果!

     讲了这么多,总结一下三种适配器模式的应用场景:

    类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

    对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。

    接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。

     

    7、装饰模式(Decorator)


    顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下:

    Source类是被装饰类,Decorator类是一个装饰类,可以为Source类动态的添加一些功能,代码如下:

    view plaincopy

    public interface Sourceable {  
        public void method();  
    }  

    view plaincopy

    public class Source implements Sourceable {  
      
        @Override  
        public void method() {  
            System.out.println("the original method!");  
        }  
    }  

    view plaincopy

    public class Decorator implements Sourceable {  
      
        private Sourceable source;  
          
        public Decorator(Sourceable source){  
            super();  
            this.source = source;  
        }  
        @Override  
        public void method() {  
            System.out.println("before decorator!");  
            source.method();  
            System.out.println("after decorator!");  
        }  
    }  

    测试类:

    view plaincopy

     

      public class DecoratorTest {  
        public static void main(String[] args) {  
            Sourceable source = new Source();  
            Sourceable obj = new Decorator(source);  
            obj.method();  
        }  
    }  

    输出:

    before decorator!
    the original method!
    after decorator!

    装饰器模式的应用场景:

    1、需要扩展一个类的功能。

    2、动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)

    缺点:产生过多相似的对象,不易排错!

     

    8、代理模式(Proxy)


    其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法。先来看看关系图:

     

    根据上文的阐述,代理模式就比较容易的理解了,我们看下代码:

    view plaincopy

    public interface Sourceable {  
        public void method();  
    }  

    view plaincopy

    public class Source implements Sourceable {  
      
        @Override  
        public void method() {  
            System.out.println("the original method!");  
        }  
    }  

    view plaincopy

    public class Proxy implements Sourceable {  
      
        private Source source;  
        public Proxy(){  
            super();  
            this.source = new Source();  
        }  
        @Override  
        public void method() {  
            before();  
            source.method();  
            atfer();  
        }  
        private void atfer() {  
            System.out.println("after proxy!");  
        }  
        private void before() {  
            System.out.println("before proxy!");  
        }  
    }  

    测试类:

    view plaincopy

    public class ProxyTest {  
      
        public static void main(String[] args) {  
            Sourceable source = new Proxy();  
            source.method();  
        }  
      
    }  

    输出:

    before proxy!
    the original method!
    after proxy!

    代理模式的应用场景:

    如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

    1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

    2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

    使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

     

    9、外观模式(Facade)


    外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口,看下类图:(我们以一个计算机的启动过程为例)

    我们先看下实现类:

    view plaincopy

    public class CPU {  
          
        public void startup(){  
            System.out.println("cpu startup!");  
        }  
          
        public void shutdown(){  
            System.out.println("cpu shutdown!");  
        }  
    }  

    view plaincopy

    public class Memory {  
          
        public void startup(){  
            System.out.println("memory startup!");  
        }  
          
        public void shutdown(){  
            System.out.println("memory shutdown!");  
        }  
    }  

    view plaincopy

    public class Disk {  
          
        public void startup(){  
            System.out.println("disk startup!");  
        }  
          
        public void shutdown(){  
            System.out.println("disk shutdown!");  
        }  
    }  

    view plaincopy

    public class Computer {  
        private CPU cpu;  
        private Memory memory;  
        private Disk disk;  
          
        public Computer(){  
            cpu = new CPU();  
            memory = new Memory();  
            disk = new Disk();  
        }  
          
        public void startup(){  
            System.out.println("start the computer!");  
            cpu.startup();  
            memory.startup();  
            disk.startup();  
            System.out.println("start computer finished!");  
        }  
          
        public void shutdown(){  
            System.out.println("begin to close the computer!");  
            cpu.shutdown();  
            memory.shutdown();  
            disk.shutdown();  
            System.out.println("computer closed!");  
        }  
    }  

    User类如下:

    view plaincopy

    public class User {  
      
        public static void main(String[] args) {  
            Computer computer = new Computer();  
            computer.startup();  
            computer.shutdown();  
        }  
    }  

    输出:

    start the computer!
    cpu startup!
    memory startup!
    disk startup!
    start computer finished!
    begin to close the computer!
    cpu shutdown!
    memory shutdown!
    disk shutdown!
    computer closed!

    如果我们没有Computer类,那么,CPU、Memory、Disk他们之间将会相互持有实例,产生关系,这样会造成严重的依赖,修改一个类,可能会带来其他类的修改,这不是我们想要看到的,有了Computer类,他们之间的关系被放在了Computer类里,这样就起到了解耦的作用,这,就是外观模式!

     

    10、桥接模式(Bridge)


    桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。我们来看看关系图:

    实现代码:

    先定义接口:

    view plaincopy

    public interface Sourceable {  
        public void method();  
    }  

    分别定义两个实现类:

    view plaincopy

    public class SourceSub1 implements Sourceable {  
      
        @Override  
        public void method() {  
            System.out.println("this is the first sub!");  
        }  
    }  

    view plaincopy

    public class SourceSub2 implements Sourceable {  
      
        @Override  
        public void method() {  
            System.out.println("this is the second sub!");  
        }  
    }  

    定义一个桥,持有Sourceable的一个实例:

    view plaincopy

    public abstract class Bridge {  
        private Sourceable source;  
      
        public void method(){  
            source.method();  
        }  
          
        public Sourceable getSource() {  
            return source;  
        }  
      
        public void setSource(Sourceable source) {  
            this.source = source;  
        }  
    }  

    view plaincopy

    public class MyBridge extends Bridge {  
        public void method(){  
            getSource().method();  
        }  
    }  

    测试类:

    view plaincopy

     public class BridgeTest {  
    
          
        public static void main(String[] args) {  
              
            Bridge bridge = new MyBridge();  
              
            /*调用第一个对象*/  
            Sourceable source1 = new SourceSub1();  
            bridge.setSource(source1);  
            bridge.method();  
              
            /*调用第二个对象*/  
            Sourceable source2 = new SourceSub2();  
            bridge.setSource(source2);  
            bridge.method();  
        }  
    }  

    output:

    this is the first sub!
    this is the second sub!

    这样,就通过对Bridge类的调用,实现了对接口Sourceable的实现类SourceSub1和SourceSub2的调用。接下来我再画个图,大家就应该明白了,因为这个图是我们JDBC连接的原理,有数据库学习基础的,一结合就都懂了。

     

     

    11、组合模式(Composite)


    组合模式有时又叫部分-整体模式在处理类似树形结构的问题时比较方便,看看关系图:

    直接来看代码:

    view plaincopy

    public class TreeNode {  
          
        private String name;  
        private TreeNode parent;  
        private Vector<TreeNode> children = new Vector<TreeNode>();  
          
        public TreeNode(String name){  
            this.name = name;  
        }  
      
        public String getName() {  
            return name;  
        }  
      
        public void setName(String name) {  
            this.name = name;  
        }  
      
        public TreeNode getParent() {  
            return parent;  
        }  
      
        public void setParent(TreeNode parent) {  
            this.parent = parent;  
        }  
          
        //添加孩子节点  
        public void add(TreeNode node){  
            children.add(node);  
        }  
          
        //删除孩子节点  
        public void remove(TreeNode node){  
            children.remove(node);  
        }  
          
        //取得孩子节点  
        public Enumeration<TreeNode> getChildren(){  
            return children.elements();  
        }  
    }  

    view plaincopy

    public class Tree {  
      
        TreeNode root = null;  
      
        public Tree(String name) {  
            root = new TreeNode(name);  
        }  
      
        public static void main(String[] args) {  
            Tree tree = new Tree("A");  
            TreeNode nodeB = new TreeNode("B");  
            TreeNode nodeC = new TreeNode("C");  
              
            nodeB.add(nodeC);  
            tree.root.add(nodeB);  
            System.out.println("build the tree finished!");  
        }  
    }  

    使用场景:将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,数等。

     

    12、享元模式(Flyweight)


    享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。

    FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。一提到共享池,我们很容易联想到Java里面的JDBC连接池,想想每个连接的特点,我们不难总结出:适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理,建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。

    看个例子:

    看下数据库连接池的代码:

    view plaincopy

    public class ConnectionPool {  
          
        private Vector<Connection> pool;  
          
        /*公有属性*/  
        private String url = "jdbc:mysql://localhost:3306/test";  
        private String username = "root";  
        private String password = "root";  
        private String driverClassName = "com.mysql.jdbc.Driver";  
      
        private int poolSize = 100;  
        private static ConnectionPool instance = null;  
        Connection conn = null;  
      
        /*构造方法,做一些初始化工作*/  
        private ConnectionPool() {  
            pool = new Vector<Connection>(poolSize);  
      
            for (int i = 0; i < poolSize; i++) {  
                try {  
                    Class.forName(driverClassName);  
                    conn = DriverManager.getConnection(url, username, password);  
                    pool.add(conn);  
                } catch (ClassNotFoundException e) {  
                    e.printStackTrace();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
      
        /* 返回连接到连接池 */  
        public synchronized void release() {  
            pool.add(conn);  
        }  
      
        /* 返回连接池中的一个数据库连接 */  
        public synchronized Connection getConnection() {  
            if (pool.size() > 0) {  
                Connection conn = pool.get(0);  
                pool.remove(conn);  
                return conn;  
            } else {  
                return null;  
            }  
        }  
    }  

    通过连接池的管理,实现了数据库连接的共享,不需要每一次都重新创建连接,节省了数据库重新创建的开销,提升了系统的性能!

     

     C、关系模式(11种)


    先来张图,看看这11中模式的关系:

    第一类:通过父类与子类的关系进行实现。

    第二类:两个类之间。

    第三类:类的状态。

    第四类:通过中间类

     

    父类与子类关系


    13、策略模式(strategy)

    策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数,关系图如下:

    图中ICalculator提供同意的方法,
    AbstractCalculator是辅助类,提供辅助方法,接下来,依次实现下每个类:

    首先统一接口:

    view plaincopy

    public interface ICalculator {  
        public int calculate(String exp);  
    }  

    辅助类:

    view plaincopy

    public abstract class AbstractCalculator {  
          
        public int[] split(String exp,String opt){  
            String array[] = exp.split(opt);  
            int arrayInt[] = new int[2];  
            arrayInt[0] = Integer.parseInt(array[0]);  
            arrayInt[1] = Integer.parseInt(array[1]);  
            return arrayInt;  
        }  
    }  

    三个实现类:

    view plaincopy

    public class Plus extends AbstractCalculator implements ICalculator {  
      
        @Override  
        public int calculate(String exp) {  
            int arrayInt[] = split(exp,"\\+");  
            return arrayInt[0]+arrayInt[1];  
        }  
    }  

    view plaincopy

    public class Minus extends AbstractCalculator implements ICalculator {  
      
        @Override  
        public int calculate(String exp) {  
            int arrayInt[] = split(exp,"-");  
            return arrayInt[0]-arrayInt[1];  
        }  
      
    }  

    view plaincopy

    public class Multiply extends AbstractCalculator implements ICalculator {  
      
        @Override  
        public int calculate(String exp) {  
            int arrayInt[] = split(exp,"\\*");  
            return arrayInt[0]*arrayInt[1];  
        }  
    }  

    简单的测试类:

    view plaincopy

    public class StrategyTest {  
      
        public static void main(String[] args) {  
            String exp = "2+8";  
            ICalculator cal = new Plus();  
            int result = cal.calculate(exp);  
            System.out.println(result);  
        }  
    }  

    输出:10

    策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

     

    14、模板方法模式(Template Method)


    解释一下模板方法模式,就是指:一个抽象类中,有一个主方法,再定义1...n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用,先看个关系图:

    就是在AbstractCalculator类中定义一个主方法calculate,calculate()调用spilt()等,Plus和Minus分别继承AbstractCalculator类,通过对AbstractCalculator的调用实现对子类的调用,看下面的例子:

    view plaincopy

    public abstract class AbstractCalculator {  
          
        /*主方法,实现对本类其它方法的调用*/  
        public final int calculate(String exp,String opt){  
            int array[] = split(exp,opt);  
            return calculate(array[0],array[1]);  
        }  
          
        /*被子类重写的方法*/  
        abstract public int calculate(int num1,int num2);  
          
        public int[] split(String exp,String opt){  
            String array[] = exp.split(opt);  
            int arrayInt[] = new int[2];  
            arrayInt[0] = Integer.parseInt(array[0]);  
            arrayInt[1] = Integer.parseInt(array[1]);  
            return arrayInt;  
        }  
    }  

    view plaincopy

    public class Plus extends AbstractCalculator {  
      
        @Override  
        public int calculate(int num1,int num2) {  
            return num1 + num2;  
        }  
    }  

    测试类:

    view plaincopy

    public class StrategyTest {  
      
        public static void main(String[] args) {  
            String exp = "8+8";  
            AbstractCalculator cal = new Plus();  
            int result = cal.calculate(exp, "\\+");  
            System.out.println(result);  
        }  
    }  

    我跟踪下这个小程序的执行过程:首先将exp和"\\+"做参数,调用AbstractCalculator类里的calculate(String,String)方法,在calculate(String,String)里调用同类的split(),之后再调用calculate(int ,int)方法,从这个方法进入到子类中,执行完return num1 + num2后,将值返回到AbstractCalculator类,赋给result,打印出来。正好验证了我们开头的思路。

     

    类之间的关系

    15、观察者模式(Observer)


    包括这个模式在内的接下来的四个模式,都是类和类之间的关系,不涉及到继承,学的时候应该 记得归纳,记得本文最开始的那个图。观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。先来看看关系图:

    我解释下这些类的作用:MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。我们看实现代码:

    一个Observer接口:

    view plaincopy

    public interface Observer {  
        public void update();  
    }  

    两个实现类:

    view plaincopy

    public class Observer1 implements Observer {  
      
        @Override  
        public void update() {  
            System.out.println("observer1 has received!");  
        }  
    }  

    view plaincopy

    public class Observer2 implements Observer {  
      
        @Override  
        public void update() {  
            System.out.println("observer2 has received!");  
        }  
      
    }  

    Subject接口及实现类:

    view plaincopy

    public interface Subject {  
          
        /*增加观察者*/  
        public void add(Observer observer);  
          
        /*删除观察者*/  
        public void del(Observer observer);  
          
        /*通知所有的观察者*/  
        public void notifyObservers();  
          
        /*自身的操作*/  
        public void operation();  
    }  

    view plaincopy

    public abstract class AbstractSubject implements Subject {  
      
        private Vector<Observer> vector = new Vector<Observer>();  
        @Override  
        public void add(Observer observer) {  
            vector.add(observer);  
        }  
      
        @Override  
        public void del(Observer observer) {  
            vector.remove(observer);  
        }  
      
        @Override  
        public void notifyObservers() {  
            Enumeration<Observer> enumo = vector.elements();  
            while(enumo.hasMoreElements()){  
                enumo.nextElement().update();  
            }  
        }  
    }  

    view plaincopy

    public class MySubject extends AbstractSubject {  
      
        @Override  
        public void operation() {  
            System.out.println("update self!");  
            notifyObservers();  
        }  
      
    }  


    测试类:

    view plaincopy

    public class ObserverTest {  
      
        public static void main(String[] args) {  
            Subject sub = new MySubject();  
            sub.add(new Observer1());  
            sub.add(new Observer2());  
              
            sub.operation();  
        }  
      
    }  

    输出:

    update self!
    observer1 has received!
    observer2 has received!

     这些东西,其实不难,只是有些抽象,不太容易整体理解,建议读者:根据关系图,新建项目,自己写代码(或者参考我的代码),按照总体思路走一遍,这样才能体会它的思想,理解起来容易!

     

     

    16、迭代子模式(Iterator)


    顾名思义,迭代器模式就是顺序访问聚集中的对象,一般来说,集合中非常常见,如果对集合类比较熟悉的话,理解本模式会十分轻松。这句话包含两层意思:一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问。我们看下关系图:

     

    这个思路和我们常用的一模一样,MyCollection中定义了集合的一些操作,MyIterator中定义了一系列迭代操作,且持有Collection实例,我们来看看实现代码:

    两个接口:

    view plaincopy

    public interface Collection {  
          
        public Iterator iterator();  
          
        /*取得集合元素*/  
        public Object get(int i);  
          
        /*取得集合大小*/  
        public int size();  
    }  

    view plaincopy

    public interface Iterator {  
        //前移  
        public Object previous();  
          
        //后移  
        public Object next();  
        public boolean hasNext();  
          
        //取得第一个元素  
        public Object first();  
    }  

    两个实现:

    view plaincopy

    public class MyCollection implements Collection {  
      
        public String string[] = {"A","B","C","D","E"};  
        @Override  
        public Iterator iterator() {  
            return new MyIterator(this);  
        }  
      
        @Override  
        public Object get(int i) {  
            return string[i];  
        }  
      
        @Override  
        public int size() {  
            return string.length;  
        }  
    }  

    view plaincopy

    public class MyIterator implements Iterator {  
      
        private Collection collection;  
        private int pos = -1;  
          
        public MyIterator(Collection collection){  
            this.collection = collection;  
        }  
          
        @Override  
        public Object previous() {  
            if(pos > 0){  
                pos--;  
            }  
            return collection.get(pos);  
        }  
      
        @Override  
        public Object next() {  
            if(pos<collection.size()-1){  
                pos++;  
            }  
            return collection.get(pos);  
        }  
      
        @Override  
        public boolean hasNext() {  
            if(pos<collection.size()-1){  
                return true;  
            }else{  
                return false;  
            }  
        }  
      
        @Override  
        public Object first() {  
            pos = 0;  
            return collection.get(pos);  
        }  
      
    }  

    测试类:

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
            Collection collection = new MyCollection();  
            Iterator it = collection.iterator();  
              
            while(it.hasNext()){  
                System.out.println(it.next());  
            }  
        }  
    }  

    输出:A B C D E

    此处我们貌似模拟了一个集合类的过程,感觉是不是很爽?其实JDK中各个类也都是这些基本的东西,加一些设计模式,再加一些优化放到一起的,只要我们把这些东西学会了,掌握好了,我们也可以写出自己的集合类,甚至框架!

    17、责任链模式(Chain of Responsibility)


    接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。先看看关系图:

     

     

     

    Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象,MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。

    view plaincopy

    public interface Handler {  
        public void operator();  
    }  

    view plaincopy

    public abstract class AbstractHandler {  
          
        private Handler handler;  
      
        public Handler getHandler() {  
            return handler;  
        }  
      
        public void setHandler(Handler handler) {  
            this.handler = handler;  
        }  
          
    }  

    view plaincopy

    public class MyHandler extends AbstractHandler implements Handler {  
      
        private String name;  
      
        public MyHandler(String name) {  
            this.name = name;  
        }  
      
        @Override  
        public void operator() {  
            System.out.println(name+"deal!");  
            if(getHandler()!=null){  
                getHandler().operator();  
            }  
        }  
    }  

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
            MyHandler h1 = new MyHandler("h1");  
            MyHandler h2 = new MyHandler("h2");  
            MyHandler h3 = new MyHandler("h3");  
      
            h1.setHandler(h2);  
            h2.setHandler(h3);  
      
            h1.operator();  
        }  
    }  

    输出:

    h1deal!
    h2deal!
    h3deal!

    此处强调一点就是,链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。

     

     18、命令模式(Command)


    命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行。这个过程好在,三者相互解耦,任何一方都不用去依赖其他人,只需要做好自己的事儿就行,司令员要的是结果,不会去关注到底士兵是怎么实现的。我们看看关系图:

    Invoker是调用者(司令员),Receiver是被调用者(士兵),MyCommand是命令,实现了Command接口,持有接收对象,看实现代码:

    view plaincopy

    public interface Command {  
        public void exe();  
    }  
    

    view plaincopy

    public class MyCommand implements Command {  
      
        private Receiver receiver;  
          
        public MyCommand(Receiver receiver) {  
            this.receiver = receiver;  
        }  
      
        @Override  
        public void exe() {  
            receiver.action();  
        }  
    }  

    view plaincopy

    public class Receiver {  
        public void action(){  
            System.out.println("command received!");  
        }  
    }  

    view plaincopy

    public class Invoker {  
          
        private Command command;  
          
        public Invoker(Command command) {  
            this.command = command;  
        }  
      
        public void action(){  
            command.exe();  
        }  
    }  

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
            Receiver receiver = new Receiver();  
            Command cmd = new MyCommand(receiver);  
            Invoker invoker = new Invoker(cmd);  
            invoker.action();  
        }  
    }  

    输出:command received!

    这个很哈理解,命令模式的目的就是达到命令的发出者和执行者之间解耦,实现请求和执行分开,熟悉Struts的同学应该知道,Struts其实就是一种将请求和呈现分离的技术,其中必然涉及命令模式的思想!

    其实每个设计模式都是很重要的一种思想,看上去很熟,其实是因为我们在学到的东西中都有涉及,尽管有时我们并不知道,其实在Java本身的设计之中处处都有体现,像AWT、JDBC、集合类、IO管道或者是Web框架,里面设计模式无处不在。因为我们篇幅有限,很难讲每一个设计模式都讲的很详细,不过我会尽我所能,尽量在有限的空间和篇幅内,把意思写清楚了,更好让大家明白。本章不出意外的话,应该是设计模式最后一讲了,首先还是上一下上篇开头的那个图:

    本章讲讲第三类和第四类。

     

    类的状态

    19、备忘录模式(Memento)


    主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,个人觉得叫备份模式更形象些,通俗的讲下:假设有原始类A,A中有各种属性,A可以决定需要备份的属性,备忘录类B是用来存储A的一些内部状态,类C呢,就是一个用来存储备忘录的,且只能存储,不能修改等操作。做个图来分析一下:

    Original类是原始类,里面有需要保存的属性value及创建一个备忘录类,用来保存value值。Memento类是备忘录类,Storage类是存储备忘录的类,持有Memento类的实例,该模式很好理解。直接看源码:

    view plaincopy

    public class Original {  
          
        private String value;  
          
        public String getValue() {  
            return value;  
        }  
      
        public void setValue(String value) {  
            this.value = value;  
        }  
      
        public Original(String value) {  
            this.value = value;  
        }  
      
        public Memento createMemento(){  
            return new Memento(value);  
        }  
          
        public void restoreMemento(Memento memento){  
            this.value = memento.getValue();  
        }  
    }  

    view plaincopy

    public class Memento {  
          
        private String value;  
      
        public Memento(String value) {  
            this.value = value;  
        }  
      
        public String getValue() {  
            return value;  
        }  
      
        public void setValue(String value) {  
            this.value = value;  
        }  
    }  

    view plaincopy

    public class Storage {  
          
        private Memento memento;  
          
        public Storage(Memento memento) {  
            this.memento = memento;  
        }  
      
        public Memento getMemento() {  
            return memento;  
        }  
      
        public void setMemento(Memento memento) {  
            this.memento = memento;  
        }  
    }  

    测试类:

    view plaincopy

    public class Test {  
    
      
        public static void main(String[] args) {  
              
            // 创建原始类  
            Original origi = new Original("egg");  
      
            // 创建备忘录  
            Storage storage = new Storage(origi.createMemento());  
      
            // 修改原始类的状态  
            System.out.println("初始化状态为:" + origi.getValue());  
            origi.setValue("niu");  
            System.out.println("修改后的状态为:" + origi.getValue());  
      
            // 回复原始类的状态  
            origi.restoreMemento(storage.getMemento());  
            System.out.println("恢复后的状态为:" + origi.getValue());  
        }  
    }  

    输出:

    初始化状态为:egg
    修改后的状态为:niu
    恢复后的状态为:egg

    简单描述下:新建原始类时,value被初始化为egg,后经过修改,将value的值置为niu,最后倒数第二行进行恢复状态,结果成功恢复了。其实我觉得这个模式叫“备份-恢复”模式最形象。

     

    20、状态模式(State)


    核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态,所以,状态模式就两点:1、可以通过改变状态来获得不同的行为。2、你的好友能同时看到你的变化。看图:

    State类是个状态类,Context类可以实现切换,我们来看看代码:

    view plaincopy

    package com.xtfggef.dp.state;  
      
    /** 
     * 状态类的核心类 
     * 2012-12-1 
     * @author erqing 
     * 
     */  
    public class State {  
          
        private String value;  
          
        public String getValue() {  
            return value;  
        }  
      
        public void setValue(String value) {  
            this.value = value;  
        }  
      
        public void method1(){  
            System.out.println("execute the first opt!");  
        }  
          
        public void method2(){  
            System.out.println("execute the second opt!");  
        }  
    }  

    view plaincopy

    package com.xtfggef.dp.state;  
      
    /** 
     * 状态模式的切换类   2012-12-1 
     * @author erqing 
     *  
     */  
    public class Context {  
      
        private State state;  
      
        public Context(State state) {  
            this.state = state;  
        }  
      
        public State getState() {  
            return state;  
        }  
      
        public void setState(State state) {  
            this.state = state;  
        }  
      
        public void method() {  
            if (state.getValue().equals("state1")) {  
                state.method1();  
            } else if (state.getValue().equals("state2")) {  
                state.method2();  
            }  
        }  
    }  

    测试类:

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
              
            State state = new State();  
            Context context = new Context(state);  
              
            //设置第一种状态  
            state.setValue("state1");  
            context.method();  
              
            //设置第二种状态  
            state.setValue("state2");  
            context.method();  
        }  
    }  

    输出:

    execute the first opt!
    execute the second opt!

    根据这个特性,状态模式在日常开发中用的挺多的,尤其是做网站的时候,我们有时希望根据对象的某一属性,区别开他们的一些功能,比如说简单的权限控制等。

     

    通过中间类

    21、访问者模式(Visitor)


    访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。—— From 百科

    简单来说,访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。简单关系图:

    来看看原码:一个Visitor类,存放要访问的对象,

    view plaincopy

    public interface Visitor {  
        public void visit(Subject sub);  
    }  

    view plaincopy

    public class MyVisitor implements Visitor {  
    
      
        @Override  
        public void visit(Subject sub) {  
            System.out.println("visit the subject:"+sub.getSubject());  
        }  
    }  

    Subject类,accept方法,接受将要访问它的对象,getSubject()获取将要被访问的属性,

    view plaincopy

    public interface Subject {  
        public void accept(Visitor visitor);  
        public String getSubject();  
    }  

    view plaincopy

    public class MySubject implements Subject {  
      
        @Override  
        public void accept(Visitor visitor) {  
            visitor.visit(this);  
        }  
      
        @Override  
        public String getSubject() {  
            return "love";  
        }  
    }  

    测试:

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
              
            Visitor visitor = new MyVisitor();  
            Subject sub = new MySubject();  
            sub.accept(visitor);      
        }  
    }  

    输出:visit the subject:love

    该模式适用场景:如果我们想为一个现有的类增加新功能,不得不考虑几个事情:1、新功能会不会与现有功能出现兼容性问题?2、以后会不会再需要添加?3、如果类不允许修改代码怎么办?面对这些问题,最好的解决方法就是使用访问者模式,访问者模式适用于数据结构相对稳定的系统,把数据结构和算法解耦,

     

    22、中介者模式(Mediator)


    中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改。如果使用中介者模式,只需关心和Mediator类的关系,具体类类之间的关系及调度交给Mediator就行,这有点像spring容器的作用。先看看图:

    User类统一接口,User1和User2分别是不同的对象,二者之间有关联,如果不采用中介者模式,则需要二者相互持有引用,这样二者的耦合度很高,为了解耦,引入了Mediator类,提供统一接口,MyMediator为其实现类,里面持有User1和User2的实例,用来实现对User1和User2的控制。这样User1和User2两个对象相互独立,他们只需要保持好和Mediator之间的关系就行,剩下的全由MyMediator类来维护!基本实现:

    view plaincopy

    public interface Mediator {  
        public void createMediator();  
        public void workAll();  
    }  

    view plaincopy

    public class MyMediator implements Mediator {  
      
        private User user1;  
        private User user2;  
          
        public User getUser1() {  
            return user1;  
        }  
      
        public User getUser2() {  
            return user2;  
        }  
      
        @Override  
        public void createMediator() {  
            user1 = new User1(this);  
            user2 = new User2(this);  
        }  
      
        @Override  
        public void workAll() {  
            user1.work();  
            user2.work();  
        }  
    }  

    view plaincopy

    public abstract class User {  
          
        private Mediator mediator;  
          
        public Mediator getMediator(){  
            return mediator;  
        }  
          
        public User(Mediator mediator) {  
            this.mediator = mediator;  
        }  
      
        public abstract void work();  
    }  

    view plaincopy

    public class User1 extends User {  
      
        public User1(Mediator mediator){  
            super(mediator);  
        }  
          
        @Override  
        public void work() {  
            System.out.println("user1 exe!");  
        }  
    }  

    view plaincopy

    public class User2 extends User {  
      
        public User2(Mediator mediator){  
            super(mediator);  
        }  
          
        @Override  
        public void work() {  
            System.out.println("user2 exe!");  
        }  
    }  

    测试类:

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
            Mediator mediator = new MyMediator();  
            mediator.createMediator();  
            mediator.workAll();  
        }  
    } 

     输出:

    user1 exe!
    user2 exe!

     

    23、解释器模式(Interpreter)


    解释器模式是我们暂时的最后一讲,一般主要应用在OOP开发中的编译器的开发中,所以适用面比较窄。

     

    Context类是一个上下文环境类,Plus和Minus分别是用来计算的实现,代码如下:

    view plaincopy

    public interface Expression {  
        public int interpret(Context context);  
    } 

    view plaincopy

    public class Plus implements Expression {  
      
        @Override  
        public int interpret(Context context) {  
            return context.getNum1()+context.getNum2();  
        }  
    }  

    view plaincopy

    public class Minus implements Expression {  
      
        @Override  
        public int interpret(Context context) {  
            return context.getNum1()-context.getNum2();  
        }  
    }  

    view plaincopy

    public class Context {  
          
        private int num1;  
        private int num2;  
          
        public Context(int num1, int num2) {  
            this.num1 = num1;  
            this.num2 = num2;  
        }  
          
        public int getNum1() {  
            return num1;  
        }  
        public void setNum1(int num1) {  
            this.num1 = num1;  
        }  
        public int getNum2() {  
            return num2;  
        }  
        public void setNum2(int num2) {  
            this.num2 = num2;  
        }  
          
          
    }  

    view plaincopy

    public class Test {  
      
        public static void main(String[] args) {  
      
            // 计算9+2-8的值  
            int result = new Minus().interpret((new Context(new Plus()  
                    .interpret(new Context(9, 2)), 8)));  
            System.out.println(result);  
        }  
    }  

    最后输出正确的结果:3。

    基本就这样,解释器模式用来做各种各样的解释器,如正则表达式等的解释器等等!

    扫码加入粉丝裙即可领取福利:

    展开全文
  • 手机AT指令

    2021-06-06 07:16:29
    ASCI码指令功能手机回答AT回车握手OKATE简化显示OKAT+CLCC来电显示OK来电话时串口输出:RINGAT+CLCC+CLCC: 1,1,4,0,0,"05133082087",129AT+CNMI=1,1,2设置收到短消息提示OK+CMTI:“SM”,44表示手机内短消息数量ATD...

    ASCI码指令

    功能

    手机回答

    AT回车

    握手

    OK

    ATE

    简化显示

    OK

    AT+CLCC

    来电显示

    OK来电话时串口输出:RING

    AT+CLCC

    +CLCC: 1,1,4,0,0,"05133082087",129

    AT+CNMI=1,1,2

    设置收到短消息提示

    OK

    +CMTI:“SM”,4

    4表示手机内短消息数量

    ATD05133082087;

    拨打05133082087电话

    AT+CMGL=0

    读取电话上全部未读过的SMS消息

    AT+CMGL=2

    列出已有的短信息

    AT+CMGL=4

    读取全部SMS消息

    AT+CMGR=X回车

    读取第X条短消息

    AT+CMGF=0回车

    用PDU格式

    AT+CMGD=X回车

    删除第X条短消息

    AT+CLIP=1,1

    来电自动显示的指令

    ERROR

    来电话!

    RING+CLIP: 13306285091,129

    AT+CMGS=6

    发送短消息的字节数

    >

    0891683108503105F011000B8131032

    65890F10008A90C665A4E0A597D00

    3100320033

    1A结束符号

    十六进制大写

    +CMGS: 45

    OK

    第45条短信发送成功!!!!!!

    AT+CMGR=1

    读取第1条短信

    0:未读过,新的短信息

    1:已读过

    第二个1表示已读

    150表示PDU数据的长度

    1表示读取第几条短信

    +CMGR: 1,1,,150

    AT指令

    一、一般命令

    AT+CGMI

    给出模块厂商的标识。SONY ERICSSON

    AT+CGMM

    获得模块标识。这个命令用来得到支持的频带(GSM900,DCS1800或PCS1900)。当模块有多频带时,回应可能是不同频带的结合。AAB-1021011-CN

    AT+CGMR

    获得改订的软件版本。R6C005      CXC125582CHINA1

    AT+CGSN

    获得GSM模块的IMEI(国际移动设备标识)序列号。351254004238596

    AT+CSCS

    选择TE特征设定。这个命令报告TE用的是哪个状态设定上的ME。ME于是可以转换每一个输入的或显示的字母。这个是用来发送、读取或者撰写短信。

    AT+CSCS?

    +CSCS: "GSM"

    AT+WPCS

    设定电话簿状态。这个特殊的命令报告通过TE电话簿所用的状态的ME。ME于是可以转换每一个输入的或者显示的字符串字母。这个用来读或者写电话簿的入口。

    NONE

    AT+CIMI

    获得IMSI。这命令用来读取或者识别SIM卡的IMSI(国际移动签署者标识)。在读取IMSI之前应该先输入PIN(如果需要PIN的话)。460001711603161

    AT+CCID

    获得SIM卡的标识。这个命令使模块读取SIM卡上的EF-CCID文件。

    NONE

    AT+GCAP

    获得能力表。(支持的功能)+GCAP: +FCLASS, +CGSM, +DS

    A/

    重复上次命令。只有A/命令不能重复。这命令重复前一个执行的命令。

    AT+CPOF

    关机。这个特殊的命令停止GSM软件堆栈和硬件层。命令AT+CFUN=0的功能与+CPOF相同。

    AT+CFUN

    设定电话机能。这个命令选择移动站点的机能水平。

    AT+CPAS

    返回移动设备的活动状态。

    AT+CMEE

    报告移动设备的错误。这个命令决定允许或不允许用结果码“+CMEERROR:”或者“+CMSERROR:”代替简单的“ERROR”。

    AT+CKPD

    小键盘控制。仿真ME小键盘执行命令。

    AT+CCLK

    时钟管理。这个命令用来设置或者获得ME真实时钟的当前日期和时间。

    AT+CCLK?

    +CCLK: "04/08/12,17:00:42+32"

    AT+CALA

    警报管理。这个命令用来设定在ME中的警报日期/时间。(闹铃)AT+CALA=?

    +CALA: (1-2),(),(),(13),()

    AT+CRMP

    铃声旋律播放。这个命令在模块的蜂鸣器上播放一段旋律。有两种旋律可用:到来语音、数据或传真呼叫旋律和到来短信声音。

    AT+CRSL

    设定或获得到来的电话铃声的声音级别。NONE

    二、呼叫控制命令

    ATD

    拨号命令。这个命令用来设置通话、数据或传真呼叫。

    ATH

    挂机命令。

    ATA

    接电话。

    AT+CEER

    扩展错误报告。这个命令给出当上一次通话设置失败后中断通话的原因。

    AT+VTD

    给用户提供应用GSM网络发送DTMF(双音多频)双音频。这个命令用来定义双音频的长度(默认值是300毫秒)。

    AT+VTS

    给用户提供应用GSM网络发送DTMF双音频。这个命令允许传送双音频。

    ATDL

    重拨上次电话号码。

    AT%Dn

    数据终端就绪(DTR)时自动拨号。

    ATS0

    自动应答。

    AT+CICB

    来电信差。

    AT+CSNS

    单一编号方案。

    AT+VGR

    AT+VGT

    增益控制。这个命令应用于调节喇叭的接收增益和麦克风的传输增益。

    AT+CMUT

    麦克风静音控制。

    AT+SPEAKER

    喇叭/麦克风选择。这个特殊命令用来选择喇叭和麦克风。

    AT+ECHO

    回音取消。

    AT+SIDET

    侧音修正。

    AT+VIP

    初始化声音参数。

    AT+DUI

    用附加的用户信息拨号。

    AT+HUI

    用附加的用户信息挂机。

    AT+RUI

    接收附加用户信息。

    三、网络服务命令

    AT+CSQ

    信号质量。+CSQ: 17,99

    AT+COPS

    服务商选择。AT+COPS?

    +COPS: 0,0,"China Mobile"

    AT+CREG

    网络注册。获得手机的注册状态。

    AT+CREG?

    +CREG: 0,1

    AT+WOPN

    读取操作员名字。NONE

    AT+CPOL

    优先操作员列表。NONE

    四、安全命令

    AT+CPIN

    输入PIN。

    AT+CPIN2

    输入PIN2。

    AT+CPINC

    PIN的剩余的尝试号码。

    AT+CLCK

    设备锁。

    AT+CPWD

    改变密码。

    五、电话簿命令

    AT+CPBS

    选择电话簿记忆存储。

    AT+CPBS?

    +CPBS: "SM"

    AT+CPBR

    读取电话簿表目。

    AT+CPBF

    查找电话簿表目。

    AT+CPBW

    写电话簿表目。

    AT+CPBP

    电话簿电话查询。

    AT+CPBN

    电话簿移动动作。这个特殊命令使电话簿中的条目前移或后移(按字母顺序)

    AT+CNUM

    签署者号码。

    AT+WAIP

    防止在下一次重起时初始化所有的电话簿。

    AT+WDCP

    删除呼叫电话号码。NONE

    AT+CSVM

    设置语音邮件号码。

    六、短消息命令

    AT+CSMS

    选择消息服务。支持的服务有GSM-MO、SMS-MT、SMS-CB。

    AT+CNMA

    新信息确认应答。

    AT+CPMS

    优先信息存储。这个命令定义用来读写信息的存储区域。

    AT+CMGF

    优先信息格式。执行格式有TEXT方式和PDU方式。

    AT+CSAS

    保存设置。保存+CSAS和+CSMP的参数。

    AT+CRES

    恢复设置。

    AT+CSDH

    显示文本方式的参数。

    AT+CNMI

    新信息指示。这个命令选择如何从网络上接收短信息。

    AT+CMGR

    读短信。信息从+CPMS命令设定的存储器读取。

    AT+CMGL

    列出存储的信息。

    AT+CMGS

    发送信息。

    AT+CMGW

    写短信息并存储。

    AT+CMSS

    从存储器中发送信息。

    AT+CSMP

    设置文本模式的参数。

    AT+CMGD

    删除短信息。删除一个或多个短信息。

    AT+CSCA

    短信服务中心地址。

    AT+CSCB

    选择单元广播信息类型。

    AT+WCBM

    单元广播信息标识。

    AT+WMSC

    信息状态(是否读过、是否发送等等)修正。

    AT+WMGO

    信息覆盖写入。

    AT+WUSS

    不改变SMS状态。在执行+CMGR或+CMGL后仍保持UNREAD。

    七、追加服务命令

    AT+CCFC

    呼叫继续。

    AT+CLCK

    呼叫禁止。

    AT+CPWD

    改变追加服务密码。

    AT+CCWA

    呼叫等待。

    AT+CLIR

    呼叫线确认限制。

    AT+CLIP

    呼叫线确认陈述。

    AT+COLP

    联络线确认陈述。

    AT+CAOC

    费用报告。

    AT+CACM

    累计呼叫计量。

    AT+CAMM

    累计呼叫计量最大值。

    AT+CPUC

    单价和货币表。

    AT+CHLD

    呼叫相关的追加服务。

    AT+CLCC

    列出当前的呼叫。

    AT+CSSN

    追加服务通知。

    AT+CUSD

    无组织的追加服务数据。

    AT+CCUG

    关闭的用户组。

    八、数据命令

    AT+CBST

    信差类型选择。

    AT+FCLASS

    选择模式。这个命令把模块设置成数据或传真操作的特殊模式。

    AT+CR

    服务报告控制。这个命令允许更为详细的服务报告。

    AT+CRC

    划分的结果代码。这个命令在呼叫到来时允许更为详细的铃声指示。

    AT+ILRR

    本地DTE-DCE速率报告。

    AT+CRLP

    无线电通信线路协议参数。

    AT+DOPT

    其他无线电通信线路参数。

    AT%C

    数据压缩选择。

    AT+DS

    是否允许V42二度数据压缩。

    AT+DR

    是否报告V42二度数据压缩。

    AT\N

    数据纠错选择。

    九、传真命令

    AT+FTM

    传送速率。

    AT+FRM

    接收速率

    AT+FTH

    用HDLC协议设置传真传送速率。

    AT+FRH

    用HDLC协议设置传真接收速率。

    AT+FTS

    停止特定时期的传送并等待。

    AT+FRS

    接收沉默。

    十、第二类传真命令

    AT+FDT

    传送数据。

    AT+FDR

    接收数据。

    AT+FET

    传送页标点。

    AT+FPTS

    页转换状态参数。

    AT+FK

    终止会议。

    AT+FBOR

    页转换字节顺序。

    AT+FBUF

    缓冲大小报告。

    AT+FCQ

    控制拷贝质量检验。

    AT+FCR

    控制接收传真的能力。

    AT+FDIS

    当前会议参数。

    AT+FDCC

    设置DCE功能参数。

    AT+FLID

    定义本地ID串。

    AT+FPHCTO

    页转换超时参数。

    十一、V24-V25命令

    AT+IPR

    确定DTE速率。

    AT+ICF

    确定DTE-DCE特征结构。

    AT+IFC

    控制DTE-DCE本地流量。

    AT&C

    设置DCD(数据携带检测)信号。

    AT&D

    设置DTR(数据终端就绪)信号。

    AT&S

    设置DST(数据设置就绪)信号。

    ATO

    回到联机模式。

    ATQ

    决定手机是否发送结果代码。

    ATV

    决定DCE响应格式。

    ATZ

    恢复为缺省设置。

    AT&W

    保存设置。

    AT&T

    自动测试。

    ATE

    决定是否回显字符。

    AT&F

    回到出厂时的设定。

    AT&V

    显示模块设置情况。

    ATI

    要求确认信息。这命令使GSM模块传送一行或多行特定的信息文字。

    AT+WMUX

    数据/命令多路复用。

    十二、特殊AT命令

    AT+CCED

    电池环境描述。

    AT+CCED

    自动RxLev指示。

    AT+WIND

    一般指示。

    AT+ALEA

    在ME和MSC之间的数据密码模式。

    AT+CRYPT

    数据密码模式。

    AT+EXPKEY

    键管理。

    AT+CPLMN

    在PLMN上的信息。

    AT+ADC

    模拟数字转换度量。

    AT+CMER

    移动设备事件报告。这个命令决定是否允许在键按下时是否主动发送结果代码。

    AT+WLPR

    读取语言偏好。

    AT+WLPW

    写语言偏好。

    AT+WIOR

    读取GPIO值。

    AT+WIOW

    写GPIO值。

    AT+WIOM

    输入/输出管理。

    AT+WAC

    忽略命令。这个特殊命令允许忽略SMS、SS和可用的PLMN。

    AT+WTONE

    播放旋律。

    AT+WDTMF

    播放DTMF旋律。

    AT+WDWL

    下载模式。

    AT+WVR

    配置信差的声音速率。

    AT+WDR

    配置数据速率。

    AT+WHWV

    显示硬件的版本。

    AT+WDOP

    显示产品的出厂日期。

    AT+WSVG

    声音增益选择。

    AT+WSTR

    返回指定状态的状态。

    AT+WSCAN

    扫描。

    AT+WRIM

    设置或返回铃声指示模式。

    AT+W32K

    是否允许32kHz掉电方式。

    AT+WCDM

    改变缺省旋律。

    AT+WSSW

    显示内部软件版本。

    AT+WCCS

    编辑或显示订制性质设置表。

    AT+WLCK

    允许在特定的操作符上个性化ME。

    AT+CPHS

    设置CPHS命令。

    AT+WBCM

    电池充电管理。

    AT+WFM

    特性管理。是否允许模块的某些特性,如带宽模式、SIM卡电压等。

    AT+WCFM

    商业特性管理。是否允许Wavecom特殊特性。

    AT+WMIR

    允许从当前存储的参数值创建定制的存储镜像。

    AT+WCDP

    改变旋律的缺省播放器。

    AT+WMBN

    设置SIM卡中的不同邮箱号码。

    十三、SIM卡工具箱命令

    AT+STSF

    配置工具箱实用程序。

    AT+STIN

    工具箱指示。

    AT+STGI

    获得从SIM卡发来的预期命令的信息。

    AT+STCR

    主动提供的结果:工具箱控制反应。

    AT+STGR

    给出响应。允许程序或用户从主菜单上选择项目,或响应某些命令。

    GSM07.05

    Function(功能)

    ATE0

    RESET

    AT+CSMS

    选择短信息服务

    AT+CPMS

    选择短信息内存

    AT+CMGF

    选择短信息格式

    AT+CSCA

    短信息中心地址

    AT+CNMI

    显示新收到的短信息

    AT+CMGR

    读短信息

    AT+CMGS

    发送短信息

    AT+CMGL

    列出SIM卡中短信息

    AT+CMSS

    从SIM内存中发短信息

    AT+CMGW

    向SIM内存中写入待发短信息

    AT+CMGD

    删除SIM内存中的短信息

    AT+CSCB

    选择蜂窝广播信息

    .设置短消息中心

    AT+CSCA=“+8613800270500”回车(具体的号码由当地的运营商决定。)

    ATZ;E回车Echo OFF

    ATZ;E1回车Echo ON

    AT+CREG?回车 回答x(X=2脱网,X=1注册,X=0状态不明)

    AT+COPS?回车 表示SIM卡是否被网络接受

    AT+COPS=?回车 显示所有可用的网络。

    5.建立语音呼叫

    AT+CREG?回车(是否网络注册)

    ATD13xxxxxxxxx;回车(语音呼叫和数据呼叫建立的区别在于号码后所接的分号上)

    6.改变并保存参数

    AT+IPR=2400回车(改变RS232口的速率至2400bps)

    AT&W回车(保存已改参数)

    7.输入PIN码

    AT+CPIN=“xxxx”

    089168

    1380513500

    11000B81

    13306285091

    0008A902----02表示短信长度,一个汉字2个字节

    0D 0A 2B 43 4D 47 4C 3A 20 31 2C 31 2C 2C 31 35 30 0D 0A 30 38 39 31 36 38 33 31 30 38 35

    30 30 31 34 35 46 30 32 34 30 44 39 31 36 38 33 31 30 33 32 36 35 38 39 30 46 31 30 30 30 38

    34 30 30 31 30 31 39 31 39 32 30 34 30 30 38 32 37 36 45 45 36 38 30 37 37 33 42 30 35 37 32

    38 34 46 34 44 34 45 38 45 34 45 31 43 37 45 43 46 30 30 33 31 30 30 33 32 30 30 33 31 30 30

    33 33 30 30 33 38 30 30 32 45 30 30 33 36 30 30 33 34 30 30 33 32 30 30 33 39 35 33 31 37 37

    45 41 43 30 30 33 33 30 30 33 31 30 30 33 34 30 30 33 38 30 30 32 45 30 30 33 34 30 30 33 37

    30 30 33 33 30 30 33 35 39 30 31 46 35 45 41 36 30 30 33 30 30 30 32 45 30 30 33 30 30 30 33

    30 36 35 42 39 34 46 34 44 38 39 44 32 30 30 33 31 30 30 33 32 30 30 33 32 30 30 32 45 30 30

    33 39 30 30 33 33 36 35 46 36 39 35 46 34 30 30 33 32 30 30 33 30 30 30 33 30 30 30 33 34 46

    46 30 44 30 30 33 30 30 30 33 39 46 46 30 44 30 30 33 32 30 30 33 34 30 30 32 30 30 30 33 32

    30 30 33 32 46 46 31 41 30 30 33 30 30 30 33 31 30 30 32 32 30 30 33 30 30 30 33 31 0D 0A

    0D 0A 4F 4B 0D 0A

    展开全文
  • Android系统完整的权限列表

    千次阅读 2021-02-08 23:10:26
    访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permission.ACCESS_COARSE_LOCATION,通过WiFi或移动基站的方式获取用户...
  • 需要一台windows系统的电脑,用于连接手机。 一共需要3步,1电脑安装驱动...电脑上管理员身份运行命令提示符,定位到adb所在目录,按住Shit鼠标点击abd目录下的空白处,选择在此处打开Powershell窗口, 原创文章 57
  • 注意,这里我们使用反射的原因是DevicePolicyManager的setActiveAdmin方法属于hide api,因此我们只好采取反射调用(如果你的操作系统Android9.0,反射调用系统API将无法顺利执行,不过暂时不清楚该机制是否对系统...
  • 最近开始接触安卓设备,了解到安卓系统开机界面以及定制桌面需要修改系统源码,这种情况下就需要重新编译系统源码得到.img镜像文件,本篇文章记录从零开始编译安卓系统源码以及安卓系统内核的一种方式。 1.配置系统...
  • 炼妖壶借助安卓自带的工作资料功能,克隆选定的应用程序,并将它们与访问沙盒外部的个人数据(包括通话记录,联系人,照片等)隔离开来,即使授予了相关权限也是如此。设备绑定的数据(短信,IMEI等)仍然可以访问。...
  • 安卓指令和命令学习总结

    千次阅读 2016-05-16 11:50:39
    安卓手机常用指令 安卓手机种类繁多,伴随着第三方深度定制系统的出现,操作也不尽相同。但是安卓手机的一些常用指令却大同小异,下面归结起来,和大家一起分享(每一条都是自己亲测过的)。 工具/原料 ...
  • 宿舍管理系统

    千次阅读 2022-02-23 19:57:01
    学生宿舍管理系统的设计与实现 DESIGN AND IMPLEMENTATION OF STUDENT DORMITORY MANAGEMENT SYSTEM 姓 名: 张三 学 号: 08220516 班 级: 05软件3 专 业: 计算机 
  • Windows11 安装安卓系统详细教程

    千次阅读 2021-10-22 22:04:04
    1、系统要求:满足Windows11要求 2、电脑版本:专业版 3、地区设置为美国,用不到Amazon store就不需要设置;(本篇是未设置地区) 4、系统设置界面,“应用” -> “可选功能” -> “更多 Windows 功能” =>...
  • 客运站车无线交互系统app是一款手机铁路办公软件,工作人员可以最便捷的享受对手持设备的操作和管理,可以进行检查车票、席位查询等诸多功能,设计实现了基于通用GPRS网络的专用数据传输协议,赶紧来下载这款软件吧...
  • Android安卓)adb指令

    2016-11-19 02:26:16
    (Android Debug Bridge)说白了就是debug工具。 adb有什么用?:借助adb工具,我们可以管理设备或手机模拟器的状态。还可以进行很多手机操作,如安装软件、系统升级、运行shell命令等等。 adb怎么用? 1.eclipse ...
  • 网上教学管理系统的设计与实现

    万次阅读 多人点赞 2019-04-14 18:54:54
    网上教学管理系统的设计与实现 第1章 绪 论 1.1 背景 为了促进计算机专业学生工程实践能力的提升,使老师能够更好的管理学生,帮助学生提高学习成绩掌握更多的专业知识,增强师生之间的交流;解决老师...
  • 系统安全相关命令su1.作用su的作用是变更为其它使用者的身份,超级用户除外,需要键入该使用者的密码。2.格式su [选项]... [-] [USER [ARG]...]3.主要参数-f,--fast:不必读启动文件(如csh.cshrc等),仅用于csh或...
  • 苹果系统iOS、macOS系统应用管理机制

    千次阅读 2020-04-12 18:28:02
    iOS、macOS系统应用管理机制 苹果系统包括:iOS、macOS、watchOS、tvOS。应用软件的生命周期为:开发、上线、安装、使用、卸载。这篇文档将从应用生命周期的各个环节介绍苹果系统对应用的管理机制,主要详细介绍iOS...
  • 本文技术涉及基于Docker容器的移动端双系统实现系统及方法,所述系统包括相互连接的内核层及应用程序层,其中,应用程序层包括Docker模块以及Docker模块根据Docker创建的多个容器,所述内核层包括LSM模块,所述LSM...
  • 看此篇文章之前大致先了解什么是AT指令,AT命令...其实安卓的拨打电话之类,底层执行的都是AT指令,包括基站。hardware\ril\reference-ril\Reference-ril.c 中 onRequest() 处理RIL_REQUEST_DIAL 时会 调用request
  • 与linux系统下常用指令的知识与操作方法看这一篇文章就够啦
  • Linux操作系统指令

    2021-11-07 18:15:47
    Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和UNIX思想的启发,是一个基于POSIX的多用户、多任务、支持多线程...
  • 深入Android系统(二)Bionic库

    千次阅读 2020-08-05 22:26:21
    Bionic库中包含了很多基本系统功能接口,这些功能大部分来自 Linux,但是和标准的 Linux 之间有很多细微差别。同时Bionic库中增加了一些新的模块(像log、linker),服务于Android的上层代码。 导读 为甚有导读呢...
  • 与Linux终端中进入、退出、连接等常见Mysql指令看这一篇文章就够啦
  • 网上单例模式的资料多如雪花,之所以写这一篇博文,是想着自己工作的结写出来是属于自己的东西,话不多说提笔就写 定义:确保某一个类只有一个实例,并且自行实例化向整个系统提供这个实例 对于系统使用某个类...
  • FileInfo.Attributes ^= FileAttributes.ReadOnly -- 没用 通过CMD删除文件/文件夹,开启管理员模式 StartInfo.Verb = "runas" -- 也无法删除 有一种方案,设置当前应用程序以管理员身份运行,即在VS的工程右键添加...
  • win11 安卓系统(WSA)安装教程

    万次阅读 多人点赞 2022-03-13 09:46:49
    目录Windows 11 安卓系统 (Sub System for Android™) 安装问题汇总准备工作==建议用手机打开本文,因为后面涉及到多次系统重启==1. 检查你的电脑是否开启了CPU虚拟化功能2. 开启 Hyper-V 和 虚拟机平台功能3. ...
  • Android Linux指令

    千次阅读 2016-06-26 18:45:25
    android下的linux指令android应用层访问底层组件1,jni 2,直接使用linux命令android系统结构1,data目录/data/data 目录:存放apk的数据目录 /data/system目录:系统配置的信息,相当于windows注册表,密码文件 /...
  • 前面提到谷歌在2014年I/O 大会上推出Android Auto的初衷是更好地保障驾驶安全,Android Automotive 也增加了驾驶模式(Drive Mode),旨在帮助汽车OEM厂商从系统层面对有可能造成驾驶分心的应用进行管理。...
  • Android--多用户模式

    万次阅读 2017-02-24 11:25:02
    通常,第一个在系统中注册的用户将默认成为系统管理员。 不同用户的设置各不相同,并且不同用户安装的应用及应用数据也不相同。但是系统中和硬件相关的设置则是共用的,例如网络设置等。 Android与Windows不同,...
  • 第一章 信息化基础知识 一、信息与信息化 1、信息论奠基者香农认为:信息就是能够用来消除不确定性的东西。 8种状态需要3位比特表示,5位比特则可表示64种状态 信息、物质材料、能源...6、信息系统生命周期可简化为:①

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,196
精华内容 2,078
关键字:

安卓系统进入管理员模式的指令