目录
一、面向对象的多态性
多态是面向对象三大特性之一
1、什么是多态性
对象在运行过程中的多种形态。
多态性我们大概可以分为两类:
(1)方法的重载与重写
(2)对象的多态性
例如:
用父类的引用指向子类对象(用大的类型去接受小的类型,向上转型、自动转换)
Chicken home = new HomeChicken();
public class Test5 {
public static void main(String[] args) {
//用父类的引用指向子类对象(用大的类型来表示小的类型),自动转换(向上转型)
Chicken hc = new HomeChicken("小鸡");
// hc.eat();
Chicken yc = new YeChicken("大鸡");
// yc.eat();
// hc=yc;
// hc.eat();
eat(hc);
eat(yc);
Chicken jjc = new JianJiaoChicken("尖叫鸡");
eat(jjc);
}
//面向抽象编程(面向接口编程)
//此处c就是传入谁的对象,这种就是抽象写法(粒度,也就是精细程度)
public static void eat(Chicken c){
System.out.println("鸡吃饭");
c.eat();
//当我们需要把父类的实例强制转换为子类引用时,为了避免类型转换异常
//那么我们需要在转换之前做类型检查(判断)
if(c instanceof JianJiaoChicken){
JianJiaoChicken jjc = (JianJiaoChicken)c;//大的类型转换为小的类型强制转换(向下转型)
}
}
}
//鸡
abstract class Chicken{
private String name;
public Chicken(){}
public Chicken(String name){
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void eat();
}
//家鸡
class HomeChicken extends Chicken{
public HomeChicken(String name){
super(name);
}
public void eat(){
System.out.println(this.getName()+",我爱吃米");
}
}
//野鸡
class YeChicken extends Chicken{
public YeChicken(String name){
super(name);
}
public void eat(){
System.out.println(this.getName()+",我爱吃虫子");
}
}
//尖叫鸡
class JianJiaoChicken extends Chicken{
public JianJiaoChicken(String name){
super(name);
}
public void eat(){
System.out.println(this.getName()+",我不吃东西");
}
}
结论:
在编程时针对对象类型的编写代码,称为面向抽象编程(或面向接口编程)
父类通常都定义为抽象类、接口
2、对象的多态性
对象多态性是从继承关系中的多个类而来,
向上转型:将子类实例转为父类引用
格式:父类 父类对象 = 子类实例;==>自动转换
以基本数据类型操作为例: int i = 'a';
(因为char的容量比int小,所以可以自动完成)
向下转型:将父类实例转化为子类实例
格式:子类 子类对象 = (子类) 父类实例;强制转换
以基本数据类型操作为例:char c = (char)97;
因为整型是4个字节比char 2个字节要大,所以需要强制完成
3、小结
方法的重载与重写就是方法的多态性表现
多个子类就是父类中的多种形态
父类引用可以指向子类对象,自动转换
子类对象指向父类引用需要强制转换(注意:类型不对会报异常)
在实际开发中尽量使用父类引用(更利于扩展)
二、instanceof关键字
1、instanceof关键字概念
instanceof关键字是用于检查对象是否为指定的类型,通常在把父类引用强制转换为子类引用时要使用,以避免发生类型转换异常(ClassCastException)
语法格式:
对象 instanceof类型 --返回boolean类型值
例:
if(homeChicken n instanceof Chicken){
//....
}
该语句一般用于判断一个对象是否为某个类的实例,是返回true,否返回false
2、父类的设计法则
通过instanceof关键字,我们可以很方便的检查对象的类型,但如果一个父类的子类过多,这样的判断还是显得很繁琐,那么如何去设计一个父类呢?
i、父类通常情况下都设计为抽象类或接口,其中优先考虑接口,如接口不能满足才考虑抽象类。
ii、一个具体的类尽可能不去继承另一个具体类,这样的好处是无需检查对象是否为父类的对象。
三、抽象类应用值模块方法设计模式
模板方法模式(Templete Method):定义一个操作中的算法的骨架,而将一些可变部分的实现延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定的步骤。
/**
* 模板方法模式(Templete Method):
* 定义一个操作中的算法的骨架,而将一些可变部分的实现延迟到子类中。
* 模板方法模式使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定的步骤。
*/
public class Test6 {
public static void main(String[] args) {
UserManager um = new UserManager();
um.action("admin","add");
}
}
abstract class BaseManager{
public void action(String name,String method){
if("admin".equals(name)){
execute(method);
}else{
System.out.println("你没有操作权限,请联系管理员");
}
}
public abstract void execute(String method);
}
class UserManager extends BaseManager{
public void execute(String method){
//用户是否登录的验证
//验证成功后才能执行以下操作
if("add".equals(method)){
System.out.println("执行添加操作");
}else if("del".equals(method)){
System.out.println("执行删除操作");
}
}
}
理解:可变的方法,就是execute方法,放在子类中,父类只需要定义一个抽象方法。
四、接口应用知策略设计模式
策略模式(Strategy Pattern),定义了一系列的算法,将每一种算法封装起来并可以相互替换使用,策略模式让算法独立于使用它的客户应用而独立变化。
OO设计原则:
1、面向接口编程(面向抽象编程)
2、封装变化
3、多用组合,少用继承
/**
* 策略模式(Strategy Pattern):
* 定义了一系列的算法,将每一种算法封装起来并可以相互替换使用,
* 策略模式让算法独立于使用它的客户应用而独立变化。
*/
public class Test7 {
public static void main(String[] args) {
BaseService us = new UserService();
us.setISave(new FileSave());
us.add("file");
us.setISave(new NetSave());
us.add("net");
}
}
//把可变的行为抽象出来,定义一系列的算法
interface ISave{
void save(String data);
}
class FileSave implements ISave{ //封装变化,把可变的东西拿出来,封装
public void save(String data){
System.out.println("把数据保存到文件中。。。"+data);
}
}
class NetSave implements ISave{
public void save(String data){
System.out.println("把数据保存到网络上。。。"+data);
}
}
abstract class BaseService{
private ISave iSave; //面向接口编程
public void setISave(ISave iSave){
this.iSave=iSave;
}
public void add(String data){
System.out.println("检查数据合法性");
iSave.save(data);
System.out.println("数据保存完毕");
}
}
class UserService extends BaseService{
}
五、Object类
Object类 是类层次结构的跟类。
每个类都使用Object作为超类,所有对象(包括数组)都实现这个类的方法;
所有的类都是Object类的子类。
1、toString()方法
public String toString()方法:返回该对象的字符串表示;
通常,toString方法会返回一个”以文本方式表示“此对象的字符串。结果应是一个简明且易读懂的信息表达式。建议所有子类都重写这个方法。
public class Test8 {
public static void main(String[] args) {
Student s = new Student("小杨",1,24);
System.out.println(s.toString());
System.out.println(s);//toString()可以省略
}
}
class Student{
private String name;
private int sid;
private int age;
public Student(){};
public Student(String name,int sid,int age){
this.name=name;
this.sid=sid;
this.age=age;
}
//重写Object类中的toString方法
public String toString(){
return "sid="+sid+",name="+name+",age="+age;
}
}
2、equals()方法
public boolean equals(Object obj):指示其他某个对象与此对象”相等“。
equals方法在非空对象引用上实现相等关系:
自反性:对于任何非空的参考值x
, x.equals(x)
应该返回true
。
对称性:对于任何非空引用值x
和y
,当且仅当y.equals(x)返回
true
,x.equals(y)
应该返回true
传递性:对于任何非空引用值x
, y
和z
,如果x.equals(y)
回报true,
y.equals(z)
回报true
,然后x.equals(z)
应该返回true
。
一致性:对于任何非空引用值x
和y
,多次调用x.equals(y)
始终返回true
或始终返回false
,没有设置中使用的信息equals
比较上的对象被修改。对于任何非空的参考值x
, x.equals(null)
应该返回false
。
3、getClass方法
public final Class<?> getClass():返回此Object
的运行时类。
返回的类
对象是被表示类的static synchronized
方法锁定的对象。
实际结果的类型是Class<? extends |X|>
其中|X|
是静态类型上其表达的擦除getClass
被调用。
例如:
在此代码片段中不需要转换:Number n = 0;
Class<? extends Number> c = n.getClass();
结果表示 :类
对象的运行时类的Class对象。
六、简单工厂设计模式
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。
public class Test9 {
public static void main(String[] args) {
//使用者和被使用者两者之间,耦合,产生了依赖,当被使用者改变时,会影响使用者
//使用工厂模式来降低两者之间的依赖
//Product phone = new Phone();
Product phone = ProductFactory.getProduct("phone");
if(null != phone){
phone.work();
}
}
}
//工厂类
class ProductFactory{
public static Product getProduct(String name){
if("phone".equals(name)){
return new Phone();
}else if("computer".equals(name)){
return new Computer();
}else {
return null;
}
}
}
interface Product{
public void work();
}
class Phone implements Product{
public void work(){
System.out.println("手机开始工作");
}
}
class Computer implements Product{
public void work(){
System.out.println("电脑开始工作");
}
}
七、静态代理设计模式
代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。
代理模式说白了就是“真是对象”的代表,在访问对象引入一定程度的间接性,因为这种间接性可以附加多种用途。
public class Test10 {
public static void main(String[] args) {
Action userAction = new UserAction();
ActionProxy proxy = new ActionProxy(userAction);
proxy.doAction();
}
}
class ActionProxy implements Action{
private Action target;//被代理的对象
public ActionProxy(Action target){
this.target=target;
}
//执行操作
public void doAction(){
long startTime = System.currentTimeMillis();
target.doAction();//执行真正的业务
long endTime = System.currentTimeMillis();
System.out.println("共耗时:"+(endTime-startTime));
}
}
interface Action{
public void doAction();
}
class UserAction implements Action{
public void doAction(){
for(int i=0;i<100;i++){
System.out.println("用户开始工作了...");
}
}
}
八、适配器设计模式
适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
public class Test11 {
public static void main(String[] args) {
PowerA powerA = new PowerAImpl();
work(powerA);
PowerB powerB = new PowerBImpl();
//work(powerB);
Adapter adapter = new Adapter(powerB);
work(adapter);
}
public static void work(PowerA a){
System.out.println("正在连接...");
a.insert();
System.out.println("工作结束...");
}
}
interface Animal{
public void sing();
public void cry();
public void run();
public void swim();
}
//适配器类
abstract class AnimalFunction{
public void sing(){}
public void cry(){}
public void run(){}
public void swim(){}
}
class Dog extends AnimalFunction{
public void run(){
System.out.println("我疯跑");
}
}
//适配器
class Adapter implements PowerA{
private PowerB powerB;
public Adapter(PowerB powerB){
this.powerB=powerB;
}
public void insert(){
powerB.connet();
}
}
interface PowerB{
public void connet();
}
class PowerBImpl implements PowerB{
public void connet() {
System.out.println("电源B开始工作");
}
}
interface PowerA{
public void insert();
}
class PowerAImpl implements PowerA{
public void insert(){
System.out.println("电源A开始工作");
}
}