面向对象与设计原则
- 三大特性
- 抽象类和接口
-
- 抽象类的三个特性(abstract)
- 接口的三个属性(interface)
- 抽象类和接口的区别
- 两者再区别
- 总结
-
- 基于接口而非实现编程
- SOLID原则
- 封装:封装也叫做信息隐匿或者数据访问保护,类通过暴露有限的访问接口,授权外部只能通过有限的方式来访问内部信息或者数据。在java语言中主要是通过public、protected、private等关键字实现的。
- 继承:是用来表示类之前的is-a关系,比如猫是一种哺乳动物。从继承关系上来讲,继承可以分为单继承和多继承,多继承就是,例如猫既可以是一种哺乳动物,也可以是一种爬行动物。继承最大的优点就是可以实现代码复用,即,可以把子类都具有的属性或者方法提取到父类当中。
- 多态:子类可以替代父类,类如
Map map = new HashMap()
,多态提高代码的扩展性和复用性。如下,whatyousay方法中可以根据传入的不同的对象输出不容的内容。
interface ProgrammingLanguage{ public void say(); }class JavaLanguage implements ProgrammingLanguage{ public void say(){ System.out.println("java 是最好的Web语言"); }; }class PhpLanguage implements ProgrammingLanguage{ public void say(){ System.out.println("php 是最好的Web语言"); }; }public class Demo{ public void whatyousay(ProgrammingLanguage language){ language.say(); } public static void main(String[] args){ ProgrammingLanguage lan = new JavaLanguage(); say(lan); } }
- 抽象类不允许被实例化只能被继承,也就是说你不能new 出来一个抽象类的对象。
- 抽象类里面有两种属性和方法
- 抽象属性和方法:只声明,不实现
- 非抽象属性和方法:声明 + 实现
- 子类实现抽象方法:子类必须实现父类中的所有抽象方法。
- 接口不能包含属性
- 接口只能声明方法,不能包含实现代码(java 8后default可以)
- 类实现接口类的时候,必须实现接口中声明的所有方法
- 【面向对象与设计原则】抽象类是对成员变量和方法的抽象,是一种
is-a
关系,是为了解决代码复用问题
is-a:代表类与类之间的继承关系 比如:猫和狗都是动物,都继承动物的特性。 所谓动物的特性就相当于抽象类中的抽象属性和方法、猫和狗都具有动物的特性,即实现动物的抽象属性
- 接口仅仅是解决对方法的抽象(抽象类 - 类的抽象),是一种
has-a
关系,是为了解决解耦问题,提高代码的可扩展性
has-a:代表对象和它的属性之间的从属关系 同一个类的对象,通过它的属性的不同值来区别 比如:小明和小红 都是同一个类(Person) 但是他们有不同的属性值 Person xiaoming = new XiaoMing("小明")是一个整体和部分的关系
- 抽象类 - 强调它是什么
B 继承 抽象类A 并实现了 A 中的抽象属性和方法,那么它就属于 A
比如 鸟(有翅膀、尖嘴、会下蛋) -继承- B(会说人话):B继承鸟类这个抽象类那么他就得实现鸟类得相关特性,所以它就是一只鹦鹉
- 接口 - 强调它有什么功能
Man 和 Woman实现 接口Person 重写 Person 中的相关方法来,但是赋予了不同内容,进而有了不同的能力
- 抽象类是为了解决代码复用问题
比如你要写所有的很多鸟相关的类、你把每个鸟都有的属性写在抽象类中、然后再在子类当中写入不同的鸟所特有的属性,这样就不用再在子类中添加这些属性。使得代码高度复用
- 接口是为了解决抽象问题
比如说你要写王者荣耀里所有的的英雄的技能,假设这些英雄都只有3个技能,那么我们就在接口中定义(技能一、技能二、技能三)即可、然后每个英雄的技能在子类中具体实现即可。
好的抽象、封装能够提高代码的灵活性,能够更好地应对需求地变化。
如下我们实现一个RabbitMq收发消息的场景,首先,这显然是一种“看似面向对象,实则面向过程”的实现,没有对代码进行有效地抽象,整个发布消息地过程实际上就是,一种代码形式的流水账,另外,一旦需求发生变化后,假如,后期将RabbitMq替换成其它的消息队列,不光是RabbitMqPub类将被废弃,使用到RabbitMqPub的地方也将面临大量的代码修改。
public class RabbitMqPub{
//用于创建MQ的物理连接
private static ConnectionFactory factory = new ConnectionFactory();
static {
//设置factory的参数 如地址、用户名、密码等
}
private Connection conn;
private Channel ch;
//获取连接
public Connection getConnection(){
if(connnect != null)return conn;
else return factory.newConnection();
}
//获取通道
public Channel getChannel(Connection conn){
if(ch != null)return ch;
else return conn.newChannel();
}
//发送消息
public void publish(Channel ch,String topic,String routeKey,String msg){
......
}
//还有订阅、连接关闭等方法
//......
}public class PublishJob{
RabbitMqPub pub = new RabbitMqPub();
public void publishMsg(){
Connnect conn = pub.getConnection();
Channel ch = pub.getChannel(conn);
pub.publish(ch,......);
}
}
下面是对上有代码的抽象封装并且使用Spring的工厂和反射的思想对MqPub进行配置,在实现多个消息队列的publish后,我们只需要在代码中对相应接口进行调用,而并不需要关心使用的是哪个消息队列,要切换消息队列也仅需在配置文件中进行更改。
public interface MqPub{
//......
public void publish(String topic,String routeKey,String msg);
}public class RabbitMqPub implements MqPub{
//用于创建MQ的物理连接
private static ConnectionFactory factory = new ConnectionFactory();
static {
//设置factory的参数 如地址、用户名、密码等
}
private Connection conn;
private Channel ch;
//获取连接
private Connection getConnection(){
if(connnect != null)return conn;
else return factory.newConnection();
}
//获取通道
private Channel getChannel(){
if(ch != null)return ch;
else return getConnection().newChannel();
}
//发送消息
public void publish(String topic,String routeKey,String msg){
.....
}
//还有订阅、连接关闭等方法
//......
}public class PublishJob{
MqPub pub = MqFactory.getMqPub();
public void publishMsg(){
pub.publish(......);
}
}public Class MqFactory{
private final String mqClassPath;
static{
String type = getProperties("XXXX");
if("rabbit".equals(type)){
mqClassPath = getProperties("XXXX");
}
} public static MqPub getMqPub(){
Class clz = Class.forName(mqClassPath)
return clz.newInstance();
}
}
SOLID原则
- 单一职责原则(Single Responsibility Principle):一个类或一个模块只负责完成一个职责
- 开闭原则(Open Close Principle):对拓展开放,对修改关闭,前者是为了应对新的需求,后者是为了保证系统的稳定性
- 里氏替换原则(Liskov Substitution Principle):子类对象能够替代父类对象出现的任何对象,并保证原来程序的逻辑行为不变及正确性不被改变。
- 接口隔离原则(Interface Segregation Principle):一个类要给多个客户端使用,那么可以为每个客户端创建一个接口,然后这个类实现所有接口,而不要只实现一个接口,其中包含所有客户端使用的方法。
- 依赖倒置原则(Dependence Inversion Principle):模块间的依赖通过抽象发生,实现类之间不发生直接的依赖,其依赖是通过抽象类或者接口产生。
推荐阅读
- 讯飞输入法PC版自定义与导入快捷短语图文详细教程
- 创建新的Windows Phone App项目(“对象引用未设置为对象的实例”错误(WP8 SDK,VS2012))
- 如何将PayPal sdk与Gradle Android集成
- C#WinFormApp DataGridView无法在List中显示对象
- 软件过程与管理知识点总结_02
- 自动将输出文件与输入文件匹配(Applescript x FFMPEG)
- 如何在Android中使用FFMPEG库将Youtube视频与MP4合并()
- Java|JVM 类加载机制与加载过程
- 使用与Android库提供的/ compileOnly依赖项
- 使用从Jackson创建的对象在Android上使用OrmLite保存子集合