攻略大全
1. 粘贴攻略
2. 造火箭攻略
3. 拧螺丝攻略
3.1 简单工厂模式(Simple Factory Pattern)
/**
* @author Renzituo
* time: 2022/11/15 22:36
* desc: 产品抽象接口,描述产品的公共接口
*/
public interface IAnimalProduct {
/**
* 可定义所有产品的抽象行为
*/
void doSomething();
}
/**
* @author Renzituo
* time: 2022/11/15 22:40
* desc: 具体产品,猫
*/
public class CatProduct implements IAnimalProduct{
@Override
public void doSomething() {
System.out.println("CatProduct");
}
}
/**
* @author Renzituo
* time: 2022/11/15 22:40
* desc: 具体产品,狗
*/
public class DogProduct implements IAnimalProduct{
@Override
public void doSomething() {
System.out.println("DogProduct");
}
}
/**
* @author Renzituo
* time: 2022/11/15 22:40
* desc: 具体产品,人
*/
public class PersonProduct implements IAnimalProduct{
@Override
public void doSomething() {
System.out.println("PersonProduct");
}
}
/**
* @author Renzituo
* time: 2022/11/15 22:38
* desc: 产品工厂:被外界调用,根据传入不同参数从而创建不同具体产品类的实例
*
*
* 简单工厂模式
* 优点:将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦;
* 把初始化实例时的工作放到工厂里进行,使代码更容易维护。 更符合面向对象的原则 & 面向接口编程,而不是面向实现编程。
*
* 缺点:工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
* 违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂;
* 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。
*
* 应用场景:客户如果只知道传入工厂类的参数,对于如何创建对象的逻辑不关心时;当工厂类负责创建的对象(具体产品)比较少时。
*
*/
class AnimalFactory {
/**
* 工厂类里使用switch语句控制生产哪种商品
* 使调用者只需要调用工厂的静态方法就可以实现产品类的实例化
* @param productName
* @return
*/
public static IAnimalProduct create(String productName) {
switch (productName) {
case "cat":
return new CatProduct();
case "dog":
return new DogProduct();
default:
return null;
}
}
}
3.2 工厂方法模式(Factory Method Pattern)
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 抽象工厂:描述具体工厂的公共接口
*/
public interface IAnimalFactory {
IAnimalProduct createAnimal();
}
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 具体工厂类,由外界直接调用进而生产
*/
public class CatFactory implements IAnimalFactory{
/**
* 通过具体工厂创建对应的产品
* @return
*/
@Override
public IAnimalProduct createAnimal() {
return new CatProduct();
}
}
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 具体工厂,由外界直接调用进而生产
*/
public class DogFactory implements IAnimalFactory{
/**
* 通过具体工厂创建对应的产品
* @return
*/
@Override
public IAnimalProduct createAnimal() {
return new DogProduct();
}
}
3.2.1 优点
- 更符合开-闭原则
- 新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
- 简单工厂模式需要修改工厂类的判断逻辑
- 符合单一职责原则
- 每个具体工厂类只负责创建对应的产品
- 简单工厂中的工厂类存在复杂的switch逻辑判断
- 不使用静态工厂方法,可以形成基于继承的等级结构
- 简单工厂模式的工厂类使用静态工厂方法
总结:工厂方法模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
3.2.2 缺点
-
添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
-
由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
-
虽然保证了工厂方法内的对外修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
-
一个具体工厂只能创建一种具体产品
3.2.3 使用场景
-
当一个类不知道它所需要的对象的类时
在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可; -
当一个类希望通过其子类来指定创建对象时
在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。 -
将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
3.3 抽象工厂模式(Abstract Factory Pattern)
3.3.1 抽象工厂类
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 抽象工厂:描述具体工厂的公共接口
*/
public interface IAnimalFactory {
IAnimal createAnimal();
IAnimal createAnimalFood();
}
3.3.2 抽象产品族
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 抽象产品族,抽象产品的父类,描述抽象产品的公共接口
*/
public abstract class IAnimal {
public abstract void doSomething();
}
3.3.3 抽象产品类
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 抽象产品,具体产品的父类,描述具体产品的公共接口
*/
public abstract class IAnimalProduct extends IAnimal{
}
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 抽象产品,具体产品的父类,描述具体产品的公共接口
*/
public abstract class IAnimalFoodProduct extends IAnimal {
}
3.3.4 具体产品类
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc
*/
public class CatProduct extends IAnimalProduct{
@Override
public void doSomething() {
System.out.println("CatProduct");
}
}
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc
*/
public class DogProduct extends IAnimalProduct{
@Override
public void doSomething() {
System.out.println("DogProduct");
}
}
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc
*/
public class CatFoodProduct extends IAnimalFoodProduct{
@Override
public void doSomething() {
System.out.println("CatFoodProduct");
}
}
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 具体产品,抽象产品的子类,工厂类的创建目标类,描述生产的具体产品
*/
public class DogFoodProduct extends IAnimalFoodProduct{
@Override
public void doSomething() {
System.out.println("DogProduct");
}
}
3.3.5 具体工厂类
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 具体工厂
*/
public class CatFactory implements IAnimalFactory{
/**
* 通过具体工厂创建对应的产品
* @return
*/
@Override
public IAnimalProduct createAnimal() {
// 生产狗
return new CatProduct();
}
@Override
public IAnimalFoodProduct createAnimalFood() {
// 生产猫粮
return new CatFoodProduct();
}
}
/**
* @author Huadao
* @date Created in 2022/11/16
* @desc 具体工厂
*/
public class DogFactory implements IAnimalFactory{
/**
* 通过具体工厂创建对应的产品
* @return
*/
@Override
public IAnimalProduct createAnimal() {
// 生产狗
return new DogProduct();
}
@Override
public IAnimalFoodProduct createAnimalFood() {
// 生产狗粮
return new DogFoodProduct();
}
}
3.3.6 优点
- 降低耦合
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展; - 更符合开-闭原则
新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可
简单工厂模式需要修改工厂类的判断逻辑
- 符合单一职责原则
每个具体工厂类只负责创建对应的产品
简单工厂中的工厂类存在复杂的switch逻辑判断
- 不使用静态工厂方法,可以形成基于继承的等级结构。
简单工厂模式的工厂类使用静态工厂方法
3.3.7 缺点
抽象工厂模式很难支持新种类产品的变化。
这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类以及所有子类的改变,这样也就违背了“开发——封闭”原则。
对于旧的产品族符合开-闭原则;对于新的产品种类不符合开-闭原则,这一特性称为开-闭原则的倾斜性。
3.3.8 应用场景
-
一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。
-
这个系统有多个系列产品,而系统中只消费其中某一系列产品
-
系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现。