2018-05-24 第十八天

一、程序设计原则:

设计模式;

别人问你设计模式是啥玩意? 为了显得很专业,你可以淡淡的说道:它是一套被反复使用,被多数人知晓的,经过分类编目的,代码设计经验的总结(心道:尼玛,还好有度娘!)

 

想要学设计模式,程序设计的6大原则,怎么可以会不清楚?

 

-闭原则(政治家,只开放不改革):对修改关闭,对扩展开放。

对原有的功能(代码)的修改是关闭(修改的越少越好)

还可以很方便的对原有功能进行扩展。

 

注:目测为黑社会大哥属性,其他小弟都要围着它转;它更像是其他五个原则的总纲,前五个原则就是围着它转的,只要我们尽量的遵守前五个原则,那么设计出来的系统应该就比较符合开闭原则了,相反,如果你违背了太多,那么你的系统或许也不太遵循开闭原则。

 

单一原则(大工匠,做事专一):每个类都只负责单一的功能,并尽量把这一个功能做到极致!

 

依赖倒置原则(艺术家,爱抽象派):高层模块不该依赖于低层模块,二者都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象。

 

接口最小化原则/接口隔离原则(大龄剩女,挑三拣四):强调的是一个接口拥有的行为应该尽可能的小。

 

注:最小接口原则一般我们是要尽量满足的,如果实在有多余的方法,这时候就轮到缺省适配器上场了。

 

里氏替换原则(大孝子,父命不敢违):一个子类应该可以替换掉父类并且可以正常工作。隐含说,子类一般不该重写父类的方法, 防止子类不能实现和父类一样的功能;

注:很多情况下,我们不必太理会它,比如模板方法模式,缺省适配器,装饰器模式等一些设计模式,就完全不搭理它。

 

迪米特原则/最小知道原则(奇葩少年,梦想是患上自闭症):一个类应当不要让外部的类知道自己太多,也不要知道外部类太多;(高内聚,低耦合)

 

二、多态polymorphism

多态的概念:多态是一种能力,一种可以父类引用指向子类对象,并可以在运行期根据对象实际的类型执行对应类型的方法 的功能。

 

多态形成的必要的条件:

1:继承。

2:父类引用指向子类对象。

3:子类重写父类的方法。父类引用调用被重写的方法。

 

1:使用父类类型作为方法的参数,传递的是子类对象。

2:使用父类类型作为方法的返回值,返回的是子类对象。

 

1:

public class TestAnimal {

 

public static void main(String[] args) {

Animal animal = new Animal();

animal.sound();

Tiger tiger = new Tiger();

tiger.sound();

Animal ani = new Tiger();

ani.sound();

}

}

 

class Animal{

void sound(){

System.out.println("小动物 吱哇乱叫!");

}

}

 

class Tiger extends Animal{

@Override

void sound() {

System.out.println("老虎 (O)〃嗷~ 的一声~~~");

}

}

 

2:

//各个国家的人在餐厅吃饭

public class TestRestaurant {

 

public static void main(String[] args) {

Restaurant restaurant = new Restaurant("卢旺达饭店");

restaurant.showEat(new Chinese("伟大的炎黄子孙"));

restaurant.showEat(new America("美利坚合众国"));

restaurant.showEat(new Japanese("小日本"));

restaurant.showEat(new Indian("阿三"));

restaurant.showEat(new Italian("意大利"));

System.out.println(restaurant);

}

 

}

//在一定程度上违背了开闭原则,只要添加一个新的Person 的子类,那么就需要在 Restaurant 重载添加一个 showEat 的方法。

// Person 引用指向 具体的其他的子类的对象。

// 多个国家的人继承了Person

// 多个国家的类 重写 Person 类的eat 方法。

class Restaurant {

private String name;

Restaurant(String name) {

this.name = name;

}

 

//void showEat(Chinese chinese){

//chinese.eat();

//}

//

//void showEat(America america){

//america.eat();

//}

//

//void showEat(Japanese japanese){

//japanese.eat();

//}

//

//void showEat(Indian indian){

//indian.eat();

//}

void showEat(Person person){

person.eat();

}

 

@Override

public String toString() {

return "Restaurant [name=" + name + "]";

}

}

 

class Person {

//国家的名字

private String countryName;

Person(String countryName) {

this.countryName = countryName;

}

 

void eat(){

System.out.println(countryName + " 的人 在吃饭!");

}

 

public String getCountryName() {

return countryName;

}

}

 

class Chinese extends Person{

public Chinese(String countryName) {

super(countryName);

}

@Override

void eat() {

System.out.println(getCountryName() + "\t 使用 筷子 吃饭!可好吃了!");

}

}

 

class America extends Person{

public America(String countryName) {

super(countryName);

}

@Override

void eat() {

System.out.println(getCountryName() + "\t 使用刀叉  四顿饭");

}

}

 

class Japanese extends Person{

public Japanese(String countryName) {

super(countryName);

}

@Override

void eat() {

System.out.println(getCountryName() + "\t 喜欢杀戮大海中的鲨鱼宝宝,然后吃掉他们的鱼鳍!真残忍啊!");

}

}

 

class Indian extends Person{

public Indian(String countryName) {

super(countryName);

}

@Override

void eat() {

System.out.println(getCountryName() + "\t 用脚揉面,然后用抓着吃!");

}

}

 

 

class Italian extends Person{

public Italian(String countryName) {

super(countryName);

}

@Override

void eat() {

System.out.println(getCountryName() + "\t 吃意大利面!味道马马虎虎吧!");

}

}

 

3:

package com.bjsxt.polymorphism.oop0524;

//人演奏乐器(大鼓Drum,吉他Guitar,钢琴Piano,小号Trumpet,三弦Trichord

public class TestInstrument {

 

public static void main(String[] args) {

People people = new People();

people.play(new Drum(10000, "大鼓"));

people.play(new Guitar(5000, "吉他"));

people.play(new Trichord(20000, "三弦"));

people.play(new Trumpet(1000, "小号"));

people.play(new Piano(200000, "钢琴"));

}

 

}

//所有的乐器的父类

class Instrument{

private int price;

private String name;

public Instrument() {

}

Instrument(int price, String name) {

super();

this.price = price;

this.name = name;

}

public int getPrice() {

return price;

}

public void setPrice(int price) {

this.price = price;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "Instrument [price=" + price + ", name=" + name + "]";

}

//这个父类的方法的实现没有太大的意义,空实现,该方法存在的意义在于被子类重写。

void sound(){

}

}

 

class Drum extends Instrument{

 

Drum(int price, String name) {

super(price, name);

}

@Override

void sound() {

System.out.println(getName() + "\t被用力的敲打,发出了。。咚咚咚。。。的声音");

}

}

 

class Guitar extends Instrument{

Guitar(int price, String name) {

super(price, name);

}

@Override

void sound() {

System.out.println(getName() + "\t 拨弄了几下,发出了,叮叮叮的声音!");

}

}

 

class Trichord extends Instrument{

Trichord(int price, String name) {

super(price, name);

}

@Override

void sound() {

System.out.println(getName() + "\t 拨弄了几下,发出了,当~~~的声音!");

}

}

 

class People{

//void play(Trichord trichord){

//trichord.sound();

//}

//void play(Drum drum){

//drum.sound();

//}

//void play(Guitar guitar){

//guitar.sound();

//}

//void play(Trumpet trumpet){

//trumpet.sound();

//}

void play(Instrument instrument){

instrument.sound();

}

}

 

class Trumpet extends Instrument{

Trumpet(int price, String name) {

super(price, name);

}

@Override

void sound() {

System.out.println(getName() + "\t 被吹了几下,发出了 嘟嘟嘟的声音");

}

}

 

class Piano extends Instrument{

Piano(int price, String name) {

super(price, name);

}

@Override

void sound() {

System.out.println(getName() + "\t 被弹了几下,发出了,叮当叮当的声音!!!");

}

}

 

三、使用多态解释方法重写

1:子类的重写方法访问权限必须大于等于父类的?

在编译期 对象无法确定 在运行期具体调用执行的哪个方法。

如果子类 降低了被访问的权限,那么如果在运行期执行的是子类重写方法,那么可以造成被重写的方法访问不到。

 

2:返回类型:

可以是父类的方法的返回类型的子类型。

因为这样做是安全的,子类对象的具有的功能是大于等于父类的。父类对象可以执行的功能,子类对象肯定没问题。

 

3:子类重写的方法可能产生的问题要小于等于父类的。

如果一个方法编译、运行的时候可能会有一些问题,那么我们必须通过代码加以处理。

如果子类的方法产生的问题更多,那么 处理父类方法的代码可能解决不掉 因为多态而调用的子类的方法产生的问题。


四、多态转型

//自动向上类型转换(小类型向大类型自动转换)  

//因为这样做是安全的。老虎当动物来用了。因为动物能做的,老虎都能做。

Animal ani = new Tiger();

//强制向下(大类型向小类型转换)  可不可以将一个动物 当老虎来用。 不能将将一个当动物用的兔子,当老虎用。

//不安全。

Animal rabbit = new Rabbit();

//强制向下类型转换的语法 ,只有当一个对象的实际类型是强制转换的类型的类型的时候,那么这种向下强转才可以成功。

Tiger tiger = (Tiger)ani;

tiger.eatRabbit();

 

1:自动向上是 多态的基础。

2:强制向下,只有当我们需要使用子类的特有的方法的时候,才有必要将父类类型的对象强制转换为子类类型。

 

//通过什么样的方式可以避免向下强转的意外。

//instanceof 的主要用途,用于判断 一个对象是否可以强制转换为指定类型的对象。

if(rabbit instanceof Tiger){

Tiger tiger1 = (Tiger)rabbit;

}

 

 

五、多态和重载

 

public class A{

public static void main(String[] args) {

A a1 = new A();

A a2 = new B();

B b = new B();

C c = new C();

D d = new D();

//a2调用的方法必须是A中存在的方法,show(A obj) 方法又被子类重写,所以执行的是子类中重写的方法

System.out.println(a2.show(b));  //B and A   ???

//a2调用的是A中存在的方法。 B没有重写show(D obj) 所以调用的就是A 中的show(D obj)

System.out.println(a2.show(d));  //A and D   ???

//b调用的是B 中有的方法  show(D obj) 是从A中继承下来的。直接调用即可。

System.out.println(b.show(d));   //A and D   ???

System.out.println(a1.show(b));  //A and A

System.out.println(a1.show(c));  //A and A

System.out.println(a1.show(d));  //A and D   

 

System.out.println(a2.show(c));  //B and A  

 

System.out.println(b.show(b));   //B and B   

System.out.println(b.show(c));   //B and B   

}

public String show(D obj){

return ("A and D");  

}   

public String show(A obj){  

return ("A and A");  

}

}   

 

class B extends A{

//B自定义的方法

public String show(B obj){

return ("B and B");  

}

//重写

public String show(A obj){

return ("B and A");  

}

//继承下来的方法

public String show(D obj){  

return ("A and D");  

}

}  

class C extends B{

public String show(B obj){

return ("B and B");  

}  

public String show(A obj){

return ("B and A");  

}

public String show(D obj){  

return ("A and D");  

}

}   

class D extends B{

public String show(B obj){

return ("B and B");  

}  

public String show(A obj){

return ("B and A");  

}

public String show(D obj){  

return ("A and D");  

}

}

 

六、简单工厂模式

java 中 有 23 种设计模式。

 

设计类的要求:高内聚、低耦合。

 

高内聚:类的内部的成员之间的关系是非常紧密的。

 

低耦合:类和类之间的耦合度要尽量小。

 

简单工厂模式的作用:降低类和类之间的耦合度的。

 

/**

 * 简单工厂模式,用来创建对象的

 *

 */

public class MyFactory {

//写一个工厂方法,通过传入的字符串的值,创建对应的类的对象并返回。

public static Person createPerson(String className){

Person  person = null;

//根据类名,给person 赋值不同的子类对象

switch(className){

case "Chinese":

person = new Chinese("炎黄子孙中国人");

break;

case "America":

person = new America("美国佬");

break;

case "Japanese":

person = new Japanese();

break;

case "Indian":

person = new Indian("阿三");

break;

case "Italian":

person = new Italian("意大利");

break;

}

return person;

}

}

 

七、单例设计模式

23 种设计模式中的很重要的一种。

 

作用:如果某一个类在一工程中只希望创建该类的唯一的一个对象。那么就可以使用单例设计模式,保证该类只被实例化一次。

 

单例设计模式:SingleTon。

 

如何去设计一个单例类。

 

public class TestSingleTon {

 

public static void main(String[] args) {

MySingltTon mySingltTon = MySingltTon.getInstance();

System.out.println(mySingltTon.getData());//0

mySingltTon.setData(10);

System.out.println(mySingltTon.getData());//10

MySingltTon mySingltTon2 = MySingltTon.getInstance();

System.out.println(mySingltTon2.getData());//10

}

}

 

需要只能被实例化一次的那个单例类。

//class MySingltTon{

////只执行一次的代码,在类加载的时候执行

////饿汉模式  可能会导致 启动延迟

//private final static MySingltTon singltTon = new MySingltTon();

//

////私有化构造方法

//private MySingltTon() {

//}

//

////写一个创建本类对象的方法。

//

////写一个得到唯一实例的方法

//public static MySingltTon getInstance(){

//return singltTon;

//}

//

//}

 

//懒汉模式

class MySingltTon{

private int data;

public int getData() {

return data;

}

 

public void setData(int data) {

this.data = data;

}

 

private static MySingltTon singltTon;

private MySingltTon() {

}

//懒汉模式  第一使用该唯一实例 的时候进行对象的初始化

  //写一个得到唯一实例的方法

public static MySingltTon getInstance(){

if(singltTon == null){

singltTon = new MySingltTon();

}

return singltTon;

}

}

 

八、final

final:可以用来修饰变量,让变量具有了不可被修改的属性。 不可变的变量。

 

final 还可以修饰什么内容?

1:修饰变量: 终态变量。

2:修饰方法: 终态方法,不能被子类重写。

3:修饰类: 终态类,不能有子类。不能被其他的类继承。

 

九、抽象类

概念:如果一个类被关键字 abstract 修饰 那么该类就是抽象类。

 

抽象类特点:

1:抽象类是不允许被实例化的。

2:抽象类只能作为类继承层次上层类,作为父类出现。

 

作用:作为父类,被其他的类继承。

 

注意:如果一个抽象类中包含了抽象方法,那么它的子类 要么声明成抽象的,要么实现所有的父类的抽象方法。

 

抽象类出现的意义:如果在做类的设计的时候,不希望设计的类被实例化,只作为父类出现,那么就可以将该类声明成 抽象的类。使用abstract  修饰一下。

 

1:抽象类中一定有抽象的方法?

答:不一定的。

2:有抽象方法的类,一定是抽象类?

答:对的。

3:抽象类是否可以用final 修饰?

答:不可以,abstract 和 final 是互斥的。

 

4:静态方法是否可以声明成抽象方法?

答:不可以的。静态的方法可以被继承,不能被重写。抽象方法需要被子类实现。语义有冲突, static abstract 互斥存在。

5:抽象类中定义的抽象方法,每一个抽象的方法都是定义了一个规则!!

答:父类在定义抽象方法的时候,对于子类实现抽象方法的功能是有要求的。但是对于实现的细节没有要求。

子类在实现的时候,必须按照父类的规则要求去实现功能,不然最终可能无法达到预期效果。

 

6:类的实例成员变量是否可以实现多态?

答:不可以实现多态。   变量的值 取决于对象中的变量的声明的类型,而不是对象中的变量的实际所在的类型。

7:静态的成员方法是否可以实现多态?

答:不可以。不能重写何来多态。

 

总结:多态是对象的多态,只针对于对象的实例方法。

 

多态的简单实现:

十、抽象类和非抽象类的异同:

相同点:

1:都是类,都是用来描述对象的。都是作为模版来使用。

2:非抽象类包含的类中的成员类型,,抽象类中都可以存在。

 

不同点:

1:抽象类不能被实例化,非抽象的可以被实例化。

2:抽象类只能作为父类使用,非抽象的既可以作为父类(没有final 修饰的)也可以不作为父类使用。

3:抽象类中可以包含抽象方法,非抽象不可以。

4:定义的方式不同,抽象类用abstract 修饰,非抽象不允许abstract

 

十一、equals

equals:Object 类的方法:

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。

Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。

 

注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

 

参数:

obj - 要与之比较的引用对象。

返回:

如果此对象与 obj 参数相同,则返回 true;否则返回 false。

 

==:判断等号

1:如果比较的两个变量的类型是基本数据类型,那么比较的值是否相等。

2:如果比较的是引用数据类型。比较的是对象的引用,首地址。

 

对于引用数据类型来说,如果想比较两个对象的内容,不能使用== 只能通过方法来实现。

Object 类的equals 方法就是做这个的。

但是 Object 类的 equals 的默认实现比较的也是地址。

 

因此,子类需要重写equals 方法。

 

例:

public class TestEquals {

 

public static void main(String[] args) {

Student s1 = new Student(12, "小刚", "");

Student s2 = new Student(12, "小刚", "");

System.out.println(s1 == s2);//false

//System.out.println(s1.equals(s2));//Object类的比较 也是false

System.out.println(s1.equals(s1));//true

System.out.println(s1.equals(null));//false

System.out.println(s1.equals("123"));//false

System.out.println(s1.equals(s2));//true

}

 

}

 

class Student{

private int age;

private String name;

private String gender;

public Student() {

}

 

Student(int age, String name, String gender) {

super();

this.age = age;

this.name = name;

this.gender = gender;

}

 

public int getAge() {

return age;

}

 

public void setAge(int age) {

this.age = age;

}

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public String getGender() {

return gender;

}

 

public void setGender(String gender) {

this.gender = gender;

}

 

@Override

public String toString() {

return "Student [age=" + age + ", name=" + name + ", gender=" + gender + "]";

}

//@Override

public boolean equals(Object obj) {

// obj 是否为null

if(obj == null){

return false;

}

//obj 和当前对象一样

if(obj == this){

return true;

}

if(!(obj instanceof Student)){

return false;

}

//比较属性

Student s = (Student)obj;

if(s.age != this.age)

return false;

if(!s.name.equals(this.name))

return false;

if(!s.gender.equals(this.gender))

return false;

return true;

}

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值