广东商城网站建设,山西省住房和城乡建设部网站,洛阳做网站公司电话,网站绑定ftp接口#xff08;interface#xff09;对于面向对象编程来说是一个非常重要的概念。它是一系列方法的声明#xff0c;却没有具体实现。有些编程语言#xff0c;比如swift#xff0c;把接口解释成“协议#xff08;protocol#xff09;”#xff0c;我觉得也是非常的恰当…接口interface对于面向对象编程来说是一个非常重要的概念。它是一系列方法的声明却没有具体实现。有些编程语言比如swift把接口解释成“协议protocol”我觉得也是非常的恰当的接口就是对方法制定的一套规范。
总结了以下几点接口的常见用法
1. 作为对类内执行流程的具体描述
这是接口的最根本的作用。有时候类内部流程的某一个环节并不是由此类自己决定的。类并不知道在这一步时具体会执行什么内容。所以需要在此处设置一枚接口提供对外界的扩展。
对于这个功能有一个非常好的范例。
一个秒表类用于测量执行某一段代码执行所需的时间。
初步的代码类似于下面这样
public class Stopwatch {private long deltaTime;public void clear() {deltaTime 0L;}public long getDeltaTime() {return deltaTime;}public void start() {long startTime System.currentTimeMillis();// do somethingdeltaTime System.currentTimeMillis() - startTime;}
}而使用Stopwatch的代码类似于这样
public static void main(String[] args) {Stopwatch stopwatch new Stopwatch();stopwatch.clear(); //时间清零stopwatch.start(); //开始运行System.out.printf(time: %dms\n,stopwatch.getDeltaTime());
}那么我们知道对于秒表这个类本身它并不能决定自己在do something那个位置将会测量什么内容的代码。
也就是说此处代码将会由Stopwatch的外部决定。所以此处可以商定一个协议也就是接口。Stopwatch决定自己开放出一个接口叫NeedMonitoringProgram需要监控的程序其中doProgram()方法就是执行需要被监控的代码。外部在使用Stopwatch时只需要去实现NeedMonitoringProgram接口也就定义好了需要监测的代码。
public interface NeedMonitoringProgram {void doProgram();
}给Stopwatch赋予NeedMonitoringProgram对象
public class Stopwatch {private long deltaTime;private NeedMonitoringProgram program;public void setProgram(NeedMonitoringProgram program) {this.program program;}public void start() {long startTime System.currentTimeMillis();program.doProgram();deltaTime System.currentTimeMillis() - startTime;}public interface NeedMonitoringProgram {void doProgram();}//省略clear()和getDeltaTime()方法
}模拟测量1到1000000叠加求和所需时间 Stopwatch stopwatch new Stopwatch();
Stopwatch.NeedMonitoringProgram program new Stopwatch.NeedMonitoringProgram() {Overridepublic void doProgram() {int sum 0;int number 1_000_000;for (int i 0; i number; i) {sum i;}System.out.printf(sum: %d\n, sum);}
};
stopwatch.setProgram(program);
stopwatch.clear();
stopwatch.start();
System.out.printf(time: %dms\n,stopwatch.getDeltaTime());假如说待测代码是需要外部参数的并且也需要返回给外部执行结果的。也可以把接口方法改进一下。
添加一个Param类来存储参数。
private Param params new Param();public void addParam(String key, Object value) {params.put(key, value);
}public interface NeedMonitoringProgramRETURN_OBJECT {RETURN_OBJECT doProgram(Param params);
}public class Param extends HashMapString, Object {}start方法也可以直接加入NeedMonitoringProgram对象减少使用时的步骤。 并且NeedMonitoringProgram类的泛型指定了返回类型。
public T T start(NeedMonitoringProgramT program) {long startTime System.currentTimeMillis();T returnObject program.doProgram(params);deltaTime System.currentTimeMillis() - startTime;return returnObject;
}在执行start()之前使用addParam()给代码赋值。而start()也会返回代码执行的结果。
Stopwatch stopwatch new Stopwatch();
stopwatch.clear();
stopwatch.addParam(number, 1_000_000);
int sum stopwatch.start(new Stopwatch.NeedMonitoringProgramInteger() {Overridepublic Integer doProgram(Stopwatch.Param params) {int sum 0;int number (Integer)params.get(number);for (int i 0; i number; i) {sum i;}return sum;}
});
System.out.printf(sum: %d\n, sum);
System.out.printf(time: %dms\n,stopwatch.getDeltaTime());运用JDK8的lambda表达式甚至可以缩写为
int sum stopwatch.start(params - {int s 0;int number (Integer)params.get(number);for (int i 0; i number; i) {s i;}return s;
});虽然java没有函数对象这一概念但是使用lambda可以充分表达一种函数式编程的思想在这里接口即等同于代表了一个函数对象。
以上是接口最最根本的功能广泛运用在AWT、Swing、Android这类图形化程序中。像XXXListener这些处理控件事件的接口都是运用了此功能。
2. 多态
可以把具体子类对象都当作父类来看屏蔽不同子类对象之间的差异。
public interface Animal {void sayHello();
}public class Cat implements Animal{Overridepublic void sayHello() {System.out.println(Im a cat.);}
}public class Dog implements Animal{Overridepublic void sayHello() {System.out.println(Im a dog.);}
}public static void main(String[] args) {Animal[] animals new Animal[]{new Cat(), new Dog()};for (Animal animal : animals) {animal.sayHello();}
}在这里把Cat和Dog都一视同仁的放入了Animal的数组内并且批量处理。多态的功能其实和抽象类abstract class相同。
3. 用于隐藏方法的具体实现过程
一个简单的Dao
public interface UserDao {User findUser(int id);void addUser(User user);void updateUser(User user);void deleteUser(int id);
}这个DaoFactory工厂类代表某一框架内部生成Dao的逻辑超简化
public class DaoFactory {public T T getDaoInstance(ClassT clazz) {if(clazz UserDao.class) {return new UserDaoImpl();} else if(……) {}}
}
那么我们在使用该框架时只需要从DaoFactory中通过Dao的类型获得该Dao的具体实现对象。
我们只关心该Dao接口有哪些我们可以用的方法而不会去关心这个Dao内部是怎么实现增删改查的。拿着这个Dao对象我们就可以去完成数据库的操作。也就是说接口为我们屏蔽了方法的具体实现屏蔽了具体的实现类中一些杂乱无章的对于使用者来说无用的中间方法。
4. 暴露分布式服务
public interface XXXService {}在大型网站项目中底层的服务都是基于分布式部署的。比如说Dubbo框架在分布式项目中接口和实现是分离于两个子项目中的。分布式的优势在于通过架设多台服务提供者provider维持了服务提供的稳定性。只要不是所有服务提供者挂机服务消费者consumer依然可以得到稳定的服务。对于服务消费者来说它并不关心服务是由谁提供的只关心有哪些服务可以用所以接口既屏蔽了方法的具体实现甚至还可以接来自不同服务提供者的服务。在这里接口起到了一个协议的作用消费者需要哪些服务由接口描述同时提供者根据接口实现了自己的处理服务逻辑。
5. 赋予类某种能力
我们常常会遇到一些诸如XXXable以able结尾的类
比如说java.io.Serializable这是赋予了类可序列化的能力
我们自己也可以写给类赋予能力的接口以及实现。
做过微信支付的应该都知道对接微信支付需要发送包含xml字符串的HTTP请求。
那么就可以对微信支付功能封装一个客户端Client
那么大致步骤如下
public class WechatClient{/*** 统一下单*/public void unifiedOrder() {//1. 生成xml//2. 发送HTTP请求//3. 处理请求结果}
}
接下来给客户端类赋予可发送HTTP请求的能力声明一个接口
public interface HttpSendable {//发送GET请求HttpResponse getHttps(String url);//发送包含raw富文本的POST请求HttpResponse postHttps(String url, String raw);
}
HttpSendable顾名思义就是可发送HTTP请求的能力
那么给客户端加上这个能力
public class WechatClient implements HttpSendable这个能力的实现可以使用抽象父类实现不会造成次要代码污染主要类的逻辑
public abstract class HttpSender implements HttpSendable{Overridepublic HttpResponse getHttps(String url) {return null;}Overridepublic HttpResponse postHttps(String url, String raw) {return null;}
}HttpSender就是HTTP的发送者当然它也有发送HTTP的能力HttpSendable然后客户端继承了它
public class WechatClient extends HttpSender implements HttpSendable{/*** 统一下单*/public void unifiedOrder() {//1. 生成xmlString xml ;//代码略//2. 发送HTTP请求HttpResponse response super.postHttps(https://, xml);//3. 处理请求结果//代码略}
}像这样写代码是不是会增加代码的可理解性了呢
6. 作为常量接口
一般老java程序员都喜欢这么用包括JDK内部也有这么用的。把一些常量扔在接口里面。
//申请状态常量
public interface ApplyStatusContants {public static final String STATIC_UNTREATED STATIC_UNTREATED;//未处理public static final String STATIC_ACCEPT STATIC_ACCEPT; //通过public static final String STATIC_REJECT STATIC_REJECT; //拒绝
}不过自从JDK1.5以后新增了enum枚举类型。我们就不需要常量接口了可以如下方式
public enum ApplyStatus {UNTREATED, ACCEPT, REJECT
}简单粗暴。
接口的用法还是特别灵活多变的也许还有没有列举的用法欢迎大家补充。