7月16号笔记
今天的主要内容:
- 对象和类的学习——联系类的构造技巧
- 数组学习——for-each
- LocalDate的学习
- 关键字的学习——final/static/this
- 工厂方法的学习【重点】
- 类的设计技巧
1. 数组的学习
-
数组定义:
int[] arr = new int[]{1,3,5,8,9,11};
-
java.util.Arrays类的使用
-
Arrays.toString(type[] a);
-
Arrays.copyOf(type[] a,int length);
-
Arrays.sort(type[] a);
-
-
TestArray
import java.util.Arrays;
public class TestArray{
public static void main(String[] args){
//数组的定义:
int[] arr = new int[]{1,3,5,8,9,11};
//Arrays.toString(type[] a);
String arrString = Arrays.toString(arr);
System.out.println("arr : " + arrString);
//Arrays.copyOf(type[] a,int length);
int[] b = Arrays.copyOf(arr,arr.length);
//Arrays.sort(type[] a)
Arrays.sort(b);
//for-each遍历数组
System.out.print("After sort : ");
for(int element:b){
System.out.print(element + " ");
}
System.out.println("\n");
}
}
/*
在JDK1.8中输出结果为:
-------------------------------
arr : [1, 3, 5, 8, 9, 11]
After sort : 1 3 5 8 9 11
-------------------------------
*/
2. java.time.LocalDate类
import java.time.LocalDate;
public class TestLocalDate{
public static void main(String[] args){
//LocalDate date1 = new LocalDate(); 不正确
//此时用静态工厂方法代表调用的构造器
LocalDate date = LocalDate.now();
System.out.println("The LocalDate : " + date);
LocalDate date2 = LocalDate.of(2018,7,16);
System.out.println("The LocalDate : " + date2);
//LocalDate类中的方法学习
int dayOfYear = date.getDayOfYear();
int dayOfMonth = date.getDayOfMonth();
int month = date.getMonthValue();
int year = date.getYear();
System.out.println("getDayOfYear() : " + dayOfYear
+ "\ngetDayOfMonth() : " + dayOfMonth
+ "\ngetMonthValue() : " + month
+ "\ngetYear() : " + year);
}
}
/*
在JDK1.8中输出结果为:
------------------------------------
The LocalDate : 2018-07-16
The LocalDate : 2018-07-16
getDayOfYear() : 197 //按照阴历计算
getDayOfMonth() : 16
getMonthValue() : 7
getYear() : 2018
------------------------------------
*/
3. 对象和类的理解
-
Employee类
-
data field:
- name,salary,hireDay
-
method:
- getName();
- getSalary();
- gethireDay();
-
class Employee
import java.time.LocalDate; class Employee{ //data field private String name; private double salary; private LocalDate hireDay; //constructor public Employee(String name,double salary,int year,int month,int day){ this.name = name; this.salary = salary; this.hireDay = LocalDate.of(year,month,day); } //method public String getName(){ return name; } public double getSalary(){ return salary; } public LocalDate gethireDay(){ return hireDay; } public void raiseSalary(double byPercent){ salary += salary * byPercent/100; } }
-
-
EmployeeTest类
public class EmployeeTest{ public static void main(String[] args){ Employee[] staff = new Employee[3]; staff[0] = new Employee("zhangsan",100,2018,7,9); staff[1] = new Employee("lisi",200,2018,7,16); staff[2] = new Employee("hahaha",300,2018,7,23); System.out.println("=====================所有员工信息======================"); //raise everyone's salary by 5% for(Employee e : staff){ e.raiseSalary(5); } //输出所有员工信息 for(Employee e : staff){ System.out.println("name : " + e.getName() + " salary : " + e.getSalary() + " hiredate : " + e.gethireDay() ); } } } /* 在JDK1.8中输出结果为: --------------------------------------------------------- =====================所有员工信息====================== name : zhangsan salary : 105.0 hiredate : 2018-07-09 name : lisi salary : 210.0 hiredate : 2018-07-16 name : hahaha salary : 315.0 hiredate : 2018-07-23 --------------------------------------------------------- */
4. 关键字的学习
-
final
- final修饰实例域(data field)时
- 确保在每一个构造器执行后,这个域的值被设置
- 在后面操作中,不能够再对它进行修改
- 例如在Employee类中name域声明为final
class Employee{ private final String name; .... }
- final关键字只是表示对象的引用不会再指示其他对象
- final修饰实例域(data field)时
-
static
- static修饰实例域时,每个类中只有一个这样的域
-
给每一个雇员一个标识码
class Employee{ private static nextID; private int id; }
-
此时这个类的所有实例共享nextID域,静态域属于类,不属于任何独立的对象
-
- static修饰实例域时,每个类中只有一个这样的域
* static修饰静态常量时,例如:
public class Math{
public static final double PI = 3.141592653.....;
}
* 此时可通过类名直接使用PI常量:Math.PI;
* static修饰方法时,表示静态方法是一种不能向对象实施操作的方法
* 静态方法不可以访问非静态的
* 非静态的可以访问静态的
-
this
-
this指示隐士参数,也就是所构造的对象
public Employee(String name,double salary){ this.name = name; this.salary = salary; }
- this指的是当前对象
-
this调用另一个构造器
public Employee(double s){
//calls Employee(String,double)
this("Employee #" + nextID.s);
nextID++;
}
-
5. 工厂方法的学习
-
使用场景
- 在任何需要生成复杂对象的地方,可以直接new的不需要工厂模式,也就是,当使用构造器无法改变所构造的类型时。
- 需要生成的对象叫做产品,生成对象的地方叫做工厂。
-
例1:吃水果时需要区分不同水果类————课堂例子
-
创建Fruit接口,定义水果eat规范
interface Fruit{ public void eat(); }
-
创建Apple和Orange两类,继承接口,实现抽象方法eat
class Apple implements Fruit{ public void eat(){ System.out.println("吃苹果"); } } class Orange implements Fruit{ public void eat(){ System.out.println("吃橘子"); } }
-
创建工厂,生产两产品
class Factory{ public static Fruit getFruit(String name){ if(name.equals("apple")){ return new Apple(); } else if(name.equals("orange")){ return new Orange(); } else{ return null; } } }
-
测试工厂类
public class Test{ public static void main(String[] args){ Factory.getFruit(args[0]).eat(); } } /* 此时程序不严谨,当输入的参数不是apple和orange时抛出java.lang.NullPointerException */
- 此时的工厂可做到需要什么取什么,而我们不需要知道内在如何完成。
-
5.1 系统学习工厂模式
一. 简单(静态)工厂
一个例子:
喜欢吃水果,此时抽象一个水果类或者接口,此时这就是产品的抽象类
abstract class Fruit{
/*
描述说过什么样,有多好吃
*/
public abstract void desc();
}
先尝尝苹果(具体的产品类)
class AppleFruit extends Fruit{
@Override
public void desc(){
System.out.println("苹果好吃还便宜,嘻嘻嘻");
}
}
再试试橘子(具体的产品类)
class OrangeFruit extends Fruit{
@Override
public void desc(){
System.out.println("橘子好久没吃了,有点酸");
}
}
还有我最爱吃的榴莲(具体的产品类)
class DurianFruit extends Fruit{
@Override
public void desc(){
System.out.println("榴莲我觉得很好吃啊");
}
}
准备工作做完了,我们来到一家“简单水果店”(简单工厂类),菜单如下:
class SimpleFruitFactory{
public static final int TYPE_APPLE = 1; //苹果
public static final int TYPE_ORANGE = 2; //橘子
public static final int TYPE_DURIAN = 3; //榴莲
public static Fruit createFruit(int type){
switch(type){
case TYPE_APPLE:
return new AppleFruit();
case TYPE_ORANGE:
return new OrangeFruit();
case TYPE_DURIAN:
return new DurianFruit();
}
}
}
简单的水果店就提供三种水果(产品),你说你要啥,他就给你啥。这里我买了一个榴莲:
/*
简单工厂模式
*/
public class Test{
public static void main(String[] args){
Fruit fruit = SimpleFruitFactory.createFruit(SimpleFruitFactory.TYPE_DURIAN);
fruit.desc();
}
}
在JDK1.8中输出结果为:
------------------
榴莲我觉得很好吃啊
-------------------
简单(静态)工厂特点
-
它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。
-
create()方法通常是静态的,所以也称之为静态工厂。
简单(静态)工厂缺点
-
扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)
-
不同的产品需要不同额外参数的时候 不支持,因为switch的原因
二. 多方法工厂(常用)
-
多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。
-
水果工厂类
class MulWayFruitFactory{ /* 吃苹果 */ public static Fruit createApple(){ return new AppleFruit(); } /* 吃橘子 */ public static Fruit createOrange(){ return new OrangeFruit(); } /* 吃榴莲 */ public static Fruit createDurian(){ return new DurianFruit(); } } //测试 public class Test{ public static void main(String[] args){ Fruit fruit = MulWayFruitFactory.createApple(); fruit.desc(); } }
- 多方法工厂一个好处在于,只需要创建产品类以及在工厂类中添加static方法即可
三. 普通工厂(常用)
- 普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。(一般->特殊)
水果生产工厂(抽象工厂类),作用就是生产水果
abstract class FruitFactory{
public abstract Fruit create();
}
苹果工厂(具体工厂类)
class AppleFactory extends FruitFactory{
@Override
public Fruit create(){
return new AppleFruit();
}
}
橘子工厂(具体工厂类)
class OrangeFactory extends FruitFactory{
@Override
public Fruit create(){
return new OrangeFruit();
}
}
榴莲工厂(具体工厂类)
class DurianFactory extends FruitFactory{
@Override
public Fruit create(){
return new DurianFruit();
}
}
测试:
public class Test{
public static void main(String[] args){
FruitFactory factory = new OrangeFactory();
factory.create().desc();
}
}
/*
在JDK1.8中输出结果为:
----------------------
橘子好久没吃了,有点酸
----------------------
*/
普通工厂和简单工厂区别:
- 普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象。
- 工厂方法使一个产品类的实例化延迟到其具体工厂子类.
- 工厂方法的好处就是更拥抱变化。当需求变化,只需要增删相应的类,不需要修改已有的类。
- 而简单工厂需要修改工厂类的create()方法,多方法静态工厂模式需要增加一个静态方法。
- 引入抽象工厂层后,每次新增一个具体产品类,也要同时新增一个具体工厂类
此工厂方法的理解转载自https://blog.csdn.net/zxt0601/article/details/52798423#commentBox
6. 块优先级的学习
-
Employee类
import java.time.LocalDate; import java.util.Random; class Employee{ private static int nextID; //data field private int id; private String name = ""; private double salary; //static块 static{ Random random = new Random(); nextID = random.nextInt(10000); } //普通块 { id =nextID; nextID++; } //三个重载方法 public Employee(String name,double salary){ this.name = name; this.salary = salary; } public Employee(double salary){ this("hahaha",salary); } public Employee(){ } public String getName(){ return name; } public double getSalary(){ return salary; } public int getId(){ return id; } }
-
EmployeeTest类
public class EmployeeTest{ public static void main(String[] args){ Employee[] staff = new Employee[3]; staff[0] = new Employee("zhangsan",100); staff[1] = new Employee(200); staff[2] = new Employee(); //输出所有员工信息 for(Employee e : staff){ System.out.println("name : " + e.getName() + " salary : " + e.getSalary() + " id : " + e.getId() ); } } } /* 在JDK1.8中输出结果为: --------------------------------------------------------- name : zhangsan salary : 100.0 id : 2269 name : hahaha salary : 200.0 id : 2270 name : salary : 0.0 id : 2271 --------------------------------------------------------- */ /* 此时可看出优先顺序 static > 普通块 */
7. 类设计技巧的学习
-
一定要保证数据私有
- 绝对不能破坏封装性
- 保持实例域的私有性
-
一定要对数据初始化
- 不要依赖系统默认值
- 显式的初始化所有的数据
- 初始化方式
- 提供默认值
- 构造其中设置默认值
-
不要在类中使用过多的基本类型
- 用其他的类代替多个相关的基本类型的使用
-
不是所有的域都需要独立的域访问器和域更改器
-
将职责过多的类进行分解
- 也不要分解到过多
-
类名和方法名要能够体现他们的职责
-
优先使用不可变的类
网友评论