举例:
之前我们创建类对象时,都是使用 new
对象的形式创建,在很多业务场景下也提供了 不直接new
的方式。
工厂模式(Factory Pattern) 是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式。
package com.app.d4_factory_pattern;
/**
* 电脑类
*/
public abstract class Computer {
private String name; // 品牌名
private double price; // 价格
/**
* 电脑开机方法
*/
public abstract void start();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
package com.app.d4_factory_pattern;
/**
* 华为电脑
*/
public class Huawei extends Computer{
@Override
public void start() {
System.out.println("价格为" + getPrice() + "元的" + getName() + "电脑已开机~~");
}
}
package com.app.d4_factory_pattern;
/**
* 苹果电脑
*/
public class Mac extends Computer{
@Override
public void start() {
System.out.println("价格为" + getPrice() + "元的" + getName() + "电脑已开机~~");
}
}
package com.app.d4_factory_pattern;
/**
* 工厂设计模式:
* 客户要买电脑,让客户输入自己想买的电脑信息,
* 根据客户输入的电脑信息来生产相应的电脑对象。
*/
public class FactoryPattern {
/**
* 在内部根据客户输入的电脑信息,为客户生产一个电脑对象返回。
* @param computerName 客户输入的电脑信息
* @return 返回一个电脑对象
*/
public static Computer createComputer(String computerName) {
switch (computerName){
case "华为":
// 如果客户输入的是华为,就生产一个华为电脑对象返回
Computer c1 = new Huawei();
c1.setName("Huawei");
c1.setPrice(6669);
return c1;
case "苹果":
// 如果客户输入的是苹果,就生产一个苹果电脑对象返回
Computer c2 = new Mac();
c2.setName("Mac");
c2.setPrice(9999.99);
return c2;
default:
// 如果客户输入的是其他信息,就返回null
return null;
}
}
}
package com.app.d4_factory_pattern;
/**
* 测试类
* 目标:理解工厂设计模式思想
*/
public class Test {
public static void main(String[] args) {
// 没有使用工厂设计模式:
// 我要买一台华为电脑
Computer c1 = new Huawei(); // 还要我自己创建华为电脑对象
// 还要我自己配置这台华为电脑
c1.setName("Huawei");
c1.setPrice(5666.9);
c1.start();
System.out.println("---------------------------");
// 使用工厂设计模式:
// 我要买一台华为电脑
Computer c2 = FactoryPattern.createComputer("华为");
c2.start();
// 我要买一台苹果电脑
Computer c3 = FactoryPattern.createComputer("苹果");
c3.start();
}
}
价格为5666.9元的Huawei电脑已开机~~
---------------------------
价格为6669.0元的Huawei电脑已开机~~
价格为9999.99元的Mac电脑已开机~~
Process finished with exit code 0
装饰模式指的是在不改变原类的基础上,动态地扩展一个类的功能。
举例:就像IO流,最初的是字节流,在不改变字节流原类的基础上,动态地扩展成缓冲字节流:
InputStream ——>抽象父类
FileInputStream ——>实现子类,读写性能较差
BufferedInputStream ——>实现子类,装饰类,读写性能高
步骤:
package com.app.d5_decorator_pattern;
/**
* 抽象的InputStream类:父类
*/
public abstract class InputStream {
public abstract int read();
public abstract int read(byte[] buffer);
}
package com.app.d5_decorator_pattern;
import java.util.Arrays;
/**
* 原始类:继承父类InputStream,实现父类定义的功能
*/
public class FileIuputStream extends InputStream {
@Override
public int read() {
System.out.println("低性能的读取了一个a");
return 97;
}
@Override
public int read(byte[] buffer) {
// 模拟读取了三滴水
buffer[0] = 97;
buffer[1] = 98;
buffer[2] = 99;
System.out.println("低性能的读取了一个数组:" + Arrays.toString(buffer));
return 3; // 返回个数
}
}
package com.app.d5_decorator_pattern;
/**
* 装饰类:继承父类InputStream,包装原始类FileInputStream,增强功能!!
*/
public class BufferedInputStream extends InputStream{
private InputStream is;
public BufferedInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() {
System.out.println("提供8KB的缓冲区,提高读取数据的性能~~");
return is.read();
}
@Override
public int read(byte[] buffer) {
System.out.println("提供8KB的缓冲区,提高读取数据的性能~~");
return is.read(buffer);
}
}
package com.app.d5_decorator_pattern;
/**
* 测试类
* 目标:理解装饰模式的思想
*/
public class Test {
public static void main(String[] args) {
// 低级的读取
FileIuputStream fis = new FileIuputStream();
System.out.println(fis.read());
System.out.println(fis.read(new byte[3]));
System.out.println("---------------------------------");
// 低级包装成高级的读取
InputStream is = new BufferedInputStream(new FileIuputStream());
System.out.println(is.read());
System.out.println(is.read(new byte[3]));
}
}
低性能的读取了一个a
97
低性能的读取了一个数组:[97, 98, 99]
3
---------------------------------
提供8KB的缓冲区,提高读取数据的性能~~
低性能的读取了一个a
97
提供8KB的缓冲区,提高读取数据的性能~~
低性能的读取了一个数组:[97, 98, 99]
3
Process finished with exit code 0