构建模式
简单工厂模式
一句话
简单工厂模式就是让一个工厂类承担构建所有对象的职责。调用者需要什么产品,让工厂生产出来即可。
缺点
- 一是如果需要生产的产品过多,此模式会导致工厂类过于庞大,承担过多的职责,变成超级类。当苹果生产过程需要修改时,要来修改此工厂。梨子生产过程需要修改时,也要来修改此工厂。也就是说这个类不止一个引起修改的原因。违背了单一职责原则。
- 二是当要生产新的产品时,必须在工厂类中添加新的分支。而开闭原则告诉我们:类应该对修改封闭。我们希望在添加新功能时,只需增加新的类,而不是修改既有的类,所以这就违背了开闭原则。
示例
- 水果工厂
public class FruitFactory { public Fruit create(String type){ switch (type){ case "苹果": return new Apple(); case "梨子": return new Pear(); default: throw new IllegalArgumentException("暂时没有这种水果"); } } }
可以把create Apple
的复杂逻辑封装在工厂内
- 调用者:
public class User { private void eat(){ FruitFactory fruitFactory = new FruitFactory(); Fruit apple = fruitFactory.create("苹果"); Fruit pear = fruitFactory.create("梨子"); apple.eat(); pear.eat(); } }
工厂方法模式
一句话
把一个大工厂拆成若干小工厂
优点
- 当生产的产品种类越来越多时,工厂类不会变成超级类。工厂类会越来越多,保持灵活。不会越来越大、变得臃肿。如果苹果的生产过程需要修改时,只需修改苹果工厂。梨子的生产过程需要修改时,只需修改梨子工厂。符合单一职责原则。
- 当需要生产新的产品时,无需更改既有的工厂,只需要添加新的工厂即可。保持了面向对象的可扩展性,符合开闭原则。
缺点
工厂太多
示例
苹果工厂:
public class AppleFactory {
public Fruit create(){
return new Apple();
}
}
梨子工厂:
public class PearFactory {
public Fruit create(){
return new Pear();
}
}
调用者:
public class User {
private void eat(){
AppleFactory appleFactory = new AppleFactory();
Fruit apple = appleFactory.create();
PearFactory pearFactory = new PearFactory();
Fruit pear = pearFactory.create();
apple.eat();
pear.eat();
}
}
抽象工厂模式
一句话
所有工厂都实现 IFactory
这个接口
Tip
抽象工厂模式适用于增加同类工厂这样的横向扩展需求,不适合新增功能这样的纵向扩展。因为接口新加一个方法会影响所有子类
优点
我们在创建时指定了具体的工厂类后,在使用时就无需再关心是哪个工厂类,只需要将此工厂当作抽象的 IFactory 接口使用即可。这种经过抽象的工厂方法模式被称作抽象工厂模式。
由于客户端只和 IFactory 打交道了,调用的是接口中的方法,使用时根本不需要知道是在哪个具体工厂中实现的这些方法,这就使得替换工厂变得非常容易。
缺点
缺点是抽象工厂模式太重了,如果 IFactory 接口需要新增功能,则会影响到所有的具体工厂类。使用抽象工厂模式,替换具体工厂时只需更改一行代码,但要新增抽象方法则需要修改所有的具体工厂类。
示例
public interface IFactory {
Fruit create();
}
然后苹果工厂和梨子工厂都实现此接口:
public class AppleFactory implements IFactory {
@Override
public Fruit create(){
return new Apple();
}
}
public class PearFactory implements IFactory {
@Override
public Fruit create(){
return new Pear();
}
}
此时,调用者可以将 AppleFactory 和 PearFactory 统一作为 IFactory 对象使用,调用者 Java 代码如下:
public class User {
private void eat(){
IFactory appleFactory = new AppleFactory();
Fruit apple = appleFactory.create();
IFactory pearFactory = new PearFactory();
Fruit pear = pearFactory.create();
apple.eat();
pear.eat();
}
}
单例模式
某个对象全局只需要一个实例时,就可以使用单例模式。
两种实现方式:饿汉式和懒汉式。
优点
- 它能够避免对象重复创建,节约空间并提升效率
- 避免由于操作不同实例导致的逻辑错误
缺点
示例
建造模式
原型模式
类似JS的object,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
优点
缺点
Warning
注意浅拷贝和深拷贝
示例
奶茶:
public class MilkTea{
public String type;
public boolean ice;
public MilkTea clone(){
MilkTea milkTea = new MilkTea();
milkTea.type = this.type;
milkTea.ice = this.ice;
return milkTea;
}
}
下单:
private void order(){
MilkTea milkTeaOfJay = new MilkTea();
milkTeaOfJay.type = "原味";
milkTeaOfJay.ice = false;
MilkTea yourMilkTea = milkTeaOfJay.clone();
// 一千位粉丝都调用 milkTeaOfJay 的 clone 方法即可
...
}