我正在尝试实现我的第一个工厂设计模式,但不确定将工厂制造的对象添加到列表时如何避免使用instanceof。这就是我想要做的:
for (ABluePrint bp : bluePrints) {
AVehicle v = AVehicleFactory.buildVehicle(bp);
allVehicles.add(v);
// Can I accomplish this without using 'instanceof'?
if (v instanceof ACar) {
cars.add((ACar) v);
} else if (v instanceof ABoat) {
boats.add((ABoat) v);
} else if (v instanceof APlane) {
planes.add((APlane) v);
}
}
根据我在SO上阅读的内容,使用“ instanceof”是一种代码味道。有没有一种更好的方法可以检查工厂创建的不使用“ instanceof”的车辆类型?
我欢迎任何有关实施的反馈/建议,因为我什至不确定我是否会采用正确的方法。
完整示例如下:
import java.util.ArrayList;
class VehicleManager {
public static void main(String[] args) {
ArrayList<ABluePrint> bluePrints = new ArrayList<ABluePrint>();
ArrayList<AVehicle> allVehicles = new ArrayList<AVehicle>();
ArrayList<ACar> cars = new ArrayList<ACar>();
ArrayList<ABoat> boats = new ArrayList<ABoat>();
ArrayList<APlane> planes = new ArrayList<APlane>();
/*
* In my application I have to access the blueprints through an API
* b/c they have already been created and stored in a data file.
* I'm creating them here just for example.
*/
ABluePrint bp0 = new ABluePrint(0);
ABluePrint bp1 = new ABluePrint(1);
ABluePrint bp2 = new ABluePrint(2);
bluePrints.add(bp0);
bluePrints.add(bp1);
bluePrints.add(bp2);
for (ABluePrint bp : bluePrints) {
AVehicle v = AVehicleFactory.buildVehicle(bp);
allVehicles.add(v);
// Can I accomplish this without using 'instanceof'?
if (v instanceof ACar) {
cars.add((ACar) v);
} else if (v instanceof ABoat) {
boats.add((ABoat) v);
} else if (v instanceof APlane) {
planes.add((APlane) v);
}
}
System.out.println("All Vehicles:");
for (AVehicle v : allVehicles) {
System.out.println("Vehicle: " + v + ", maxSpeed: " + v.maxSpeed);
}
System.out.println("Cars:");
for (ACar c : cars) {
System.out.println("Car: " + c + ", numCylinders: " + c.numCylinders);
}
System.out.println("Boats:");
for (ABoat b : boats) {
System.out.println("Boat: " + b + ", numRudders: " + b.numRudders);
}
System.out.println("Planes:");
for (APlane p : planes) {
System.out.println("Plane: " + p + ", numPropellers: " + p.numPropellers);
}
}
}
class AVehicle {
double maxSpeed;
AVehicle(double maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
class ACar extends AVehicle {
int numCylinders;
ACar(double maxSpeed, int numCylinders) {
super(maxSpeed);
this.numCylinders = numCylinders;
}
}
class ABoat extends AVehicle {
int numRudders;
ABoat(double maxSpeed, int numRudders) {
super(maxSpeed);
this.numRudders = numRudders;
}
}
class APlane extends AVehicle {
int numPropellers;
APlane(double maxSpeed, int numPropellers) {
super(maxSpeed);
this.numPropellers = numPropellers;
}
}
class AVehicleFactory {
public static AVehicle buildVehicle(ABluePrint blueprint) {
switch (blueprint.type) {
case 0:
return new ACar(100.0, 4);
case 1:
return new ABoat(65.0, 1);
case 2:
return new APlane(600.0, 2);
default:
return new AVehicle(0.0);
}
}
}
class ABluePrint {
int type; // 0 = car; // 1 = boat; // 2 = plane;
ABluePrint(int type) {
this.type = type;
}
}
您可以实现Visitor模式。
详细答案
这个想法是使用多态来执行类型检查。每个子类都覆盖该accept(Visitor)方法,该方法应在超类中声明。当我们遇到如下情况时:
void add(Vehicle vehicle) {
//what type is vehicle??
}
我们可以将一个对象传递到中声明的方法中Vehicle。如果vehicle类型为Car,并class Car覆盖我们将对象传递给的方法,则该对象现在将在Car类中声明的方法内进行处理。我们利用它的优势:创建一个Visitor对象并将其传递给重写的方法:
abstract class Vehicle {
public abstract void accept(AddToListVisitor visitor);
}
class Car extends Vehicle {
public void accept(AddToListVisitor visitor) {
//gets handled in this class
}
}
这Visitor应该准备好访问类型Car。您想要避免使用的任何类型instanceof都必须在中指定Visitor。
class AddToListVisitor {
public void visit(Car car) {
//now we know the type! do something...
}
public void visit(Plane plane) {
//now we know the type! do something...
}
}
这是类型检查的地方!
当Car接收到访问者时,它应该使用this关键字传递自己。由于我们在class中Car,因此visit(Car)将调用该方法。现在我们知道了对象的类型,就可以在访问者内部执行所需的操作。
因此,从顶部开始:
您创建一个Visitor,执行所需的操作。访问者应该visit为要对其执行操作的每种对象类型提供一个方法。在这种情况下,我们正在为车辆创建访客:
interface VehicleVisitor {
void visit(Car car);
void visit(Plane plane);
void visit(Boat boat);
}
我们要执行的动作是将车辆添加到某物上。我们将创建一个AddTransportVisitor;负责管理交通运输的访客:
class AddTransportVisitor implements VehicleVisitor {
public void visit(Car car) {
//add to car list
}
public void visit(Plane plane) {
//add to plane list
}
public void visit(Boat boat) {
//add to boat list
}
}
每辆车都应该能够接纳来访者:
abstract class Vehicle {
public abstract void accept(VehicleVisitor visitor);
}
当访客被传递到车辆时,车辆应调用其visit方法,并将自身传递给参数:
class Car extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
class Boat extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
class Plane extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
这就是类型检查的地方。visit会调用正确的方法,该方法包含根据方法的参数执行的正确代码。
最后一个问题是VehicleVisitor与列表进行交互。这就是您的VehicleManager来历:它封装了列表,使您可以通过一种VehicleManager#add(Vehicle)方法添加载具。
创建访问者时,我们可以将管理器传递给它(可能通过它的构造函数),这样,既然我们知道对象的类型,就可以执行所需的操作。本VehicleManager应包含的游客和拦截VehicleManager#add(Vehicle)来电:
class VehicleManager {
private List<Car> carList = new ArrayList<>();
private List<Boat> boatList = new ArrayList<>();
private List<Plane> planeList = new ArrayList<>();
private AddTransportVisitor addVisitor = new AddTransportVisitor(this);
public void add(Vehicle vehicle) {
vehicle.accept(addVisitor);
}
public List<Car> getCarList() {
return carList;
}
public List<Boat> getBoatList() {
return boatList;
}
public List<Plane> getPlaneList() {
return planeList;
}
}
现在,我们可以为这些AddTransportVisitor#visit方法编写实现:
class AddTransportVisitor implements VehicleVisitor {
private VehicleManager manager;
public AddTransportVisitor(VehicleManager manager) {
this.manager = manager;
}
public void visit(Car car) {
manager.getCarList().add(car);
}
public void visit(Plane plane) {
manager.getPlaneList().add(plane);
}
public void visit(Boat boat) {
manager.getBoatList().add(boat);
}
}
我强烈建议删除add每种车辆的吸气剂方法并声明重载方法。这样可以减少不需要时的“访问”开销,例如manager.add(new Car()):
class VehicleManager {
private List<Car> carList = new ArrayList<>();
private List<Boat> boatList = new ArrayList<>();
private List<Plane> planeList = new ArrayList<>();
private AddTransportVisitor addVisitor = new AddTransportVisitor(this);
public void add(Vehicle vehicle) {
vehicle.accept(addVisitor);
}
public void add(Car car) {
carList.add(car);
}
public void add(Boat boat) {
boatList.add(boat);
}
public void add(Plane plane) {
planeList.add(plane);
}
public void printAllVehicles() {
//loop through vehicles, print
}
}
class AddTransportVisitor implements VehicleVisitor {
private VehicleManager manager;
public AddTransportVisitor(VehicleManager manager) {
this.manager = manager;
}
我正在研究一个推荐系统。这将是一个Android应用程序,用户将输入他们的偏好,并在这些偏好的基础上,其他匹配的配置文件将显示给该用户。我正在从用户那里获取数据,并将其存储在Firebase中。 这些是数值,为了向用户显示匹配的配置文件,我使用两种算法来计算用户之间的相似性计数:和 由于这将是一个实时应用程序,所以这种方法是完全错误的,我想实现策略设计模式,其中算法可以在运行时决定,而不是在编译时
介绍 与创建型模式类似,工厂模式创建对象(视为工厂里的产品)时无需指定创建对象的具体类。 工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型。 这个模式十分有用,尤其是创建对象的流程赋值的时候,比如依赖于很多设置文件等。并且,你会经常在程序里看到工厂方法,用于让子类类定义需要创建的对象类型
简单工厂(Simple Factory) Intent 在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。 Class Diagram 简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个,如果不使用简单工厂,那么所
4. 抽象工厂(Abstract Factory) Intent 提供一个接口,用于创建 相关的对象家族 。 Class Diagram 抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。 抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 cr
工厂方法(Factory Method) Intent 定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。 Class Diagram 在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。 下图中,Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,这个产品对象由 factoryMethod() 方法创建。
我想知道在Spring框架中使用依赖注入的工厂模式的当前最佳实践是什么。我想知道工厂模式在使用Spring依赖注入的情况下是否仍然适用。我做了一些搜索,看到了一些过去的讨论(依赖注入vs工厂模式),但似乎有不同的观点。 我在一些现实生活中的项目中看到使用Map来保存所有的bean,并依靠自动装配来创建这些bean。当需要bean时,它使用密钥通过map获取它。 但是我看到这两种方法有些不同。 使用