文章目录
参考资料
视频资料:查看视频
在使用设计模式前,我们先用常见的方法来实现封装水果类,以及水果的继承类苹果和橘子。
- 定义一个水果抽象类
public abstract class Fruit {
// 水果抽象类
private final String name;
public Fruit(String name){
this.name = name;
}
@Override
public String toString() {
return name + "@" + hashCode(); // 打印当前水果名称和 哈希值
}
}
- 定义实现的子类
// 苹果
class Apple extends Fruit{
public Apple(){
super("苹果");
}
}
// 橘子
class Origin extends Fruit{
public Origin(){
super("橘子");
}
}
- 运行测试
public class Demo {
public static void main(String[] args) {
System.out.println(new Apple());
System.out.println(new Origin());
}
}
// 输出结果
// 苹果@685325104
// 橘子@460141958
接下来我们通过一些设计模式来改写上面的例子,以便体会不同设计模式的特点。
一、工厂方法设计模式
简单的工厂模式
基于之前的例子,我们创建一个工厂类,依此来获取创建实例
这里需注意获取实例的方法是static静态方法
public class FruitFactory {
public static Fruit getFruit(String type){
switch (type){
case "苹果":
return new Apple();
case "橘子":
return new Origin();
default:
return null;
}
}
}
通过简单工厂创建对象:
public class Demo {
public static void main(String[] args) {
Fruit apple = FruitFactory.getFruit("苹果");
System.out.println(apple);
}
}
// 输出结果
// 苹果@685325104
这种简单的工厂模式带来的弊端是:
-
不符合面向对象的开闭原则 OCP,即对扩展开发,对修改关闭。当有新的Fruit子类时,需要改写getFruit的方法
-
getFruit需要进行字符串的判断,比较鸡肋
优化: 使用抽象类+泛型,将水果工厂类进一步划分成具体的水果工厂类
public abstract class FruitFactory<T extends Fruit> {
public abstract T getFruit();
}
class AppleFactory extends FruitFactory<Apple>{
@Override
public Apple getFruit() {
return new Apple();
}
}
class OriginFactory extends FruitFactory<Origin>{
@Override
public Origin getFruit() {
return new Origin();
}
}
public class Demo {
public static void main(String[] args) {
System.out.println(new AppleFactory().getFruit());
System.out.println(new OriginFactory().getFruit());
}
}
// 输出结果
// 苹果@685325104
// 橘子@460141958
二、抽象工厂模式
之前介绍的工厂方法模式,通过定义顶层抽象工厂类,以及继承的方式,针对每一种水果产品都提供一个工厂类进行创建,这里没有涉及更复杂的概念,比如工厂不仅生产水果,而且还生产饮料之类的。
这里我们可以定义水果、饮品类,然后抽象到一个工厂里,按品牌分类。
- 定义表示水果的类,和之前一样
public abstract class Fruit {
// 水果抽象类
private final String name;
public Fruit(String name){
this.name = name;
}
@Override
public String toString() {
return name + "@" + hashCode(); // 打印当前水果名称和 哈希值
}
}
// 苹果
class Apple extends Fruit{
public Apple(){
super("苹果");
}
}
// 橘子
class Origin extends Fruit{
public Origin(){
super("橘子");
}
}
- 定义表示饮品的类,和之前表示水果类似
abstract class Drink {
// 饮品抽象类
private final String name;
public Drink(String name){
this.name = name;
}
@Override
public String toString() {
return name + "@" + hashCode(); // 打印当前水果名称和 哈希值