我有2个案例,一个方法可以被认为是工厂设计模式,这个例子是在C#中,altought,可以应用于其他编程语言:
enum NinjaTypes {
Generic,
Katanna,
StarThrower,
Invisible,
Flyer
}
public class Ninja {
public string Name { get; set; }
public void jump() { ... }
public void kickAss() { ... }
}
public class KatannaNinja: Ninja {
public void useKatanna() { ... }
}
public class StarNinja: Ninja {
public void throwStar() { ... }
}
public class InvisibleNinja: Ninja {
public void becomeInvisible() {...}
public void becomeVisible() {...}
}
public class FlyNinja: Ninja {
public void fly() {...}
public void land() {...}
}
public class NinjaSchool {
// always return generic type
public Ninja StandardStudent() {...}
// may return other types
public Ninja SpecialityStudent(NinjaTypes WhichType) {...}
}
方法StandardStudent()
始终返回相同类型的新对象SpecialityStudent(...)
,可以从共享相同超类/基类型的不同类返回新对象。这两种方法都不是虚拟的。
问题是,两种方法都是“工厂设计模式”吗?
我的猜测是SpecialityStudent(...)
是,但StandardStudent()
不是。如果第二个不是,可以考虑另一种设计模式吗?
答案 0 :(得分:3)
我认为,FactoryMethod`和AbstractFactory模式也不禁止用户使用参数为创建者方法指定类型。无论如何,你应该在设计中考虑至少两件事:
答案 1 :(得分:2)
我认为这实际上看起来像一个反模式。没有什么可以阻止这个代码的消费者直接实例化专业忍者。使用忍者学校有什么好处?我认为Factory模式的重点是封装实例化对象的过程,以便您可以隐藏消费者的详细信息。每当你对“创建”逻辑进行更改时,它都不会破坏任何人的代码。 将所有类型都放在枚举中看起来是个坏主意。除了“感觉不对”之外,我没有具体理由支持这一主张。
在查看抽象工厂模式之后,我可以看到如何将其转换为抽象工厂,但我没有看到给定对象语义的好处。我认为,如果你想拥有一个Ninja工厂,你必须使个别构造函数受到保护或内部,所以它们不能被消费者代码直接调用
答案 2 :(得分:2)
您的方法都可以视为工厂。但第二个使用起来有点尴尬:
var school = new NinjaSchool();
var ninja = school.SpecialtyStudent(NinjaTypes.Flyer);
// to fly you must cast
((FlyingNinja)ninja).Fly();
你已经要求传单了,所以你不需要演员。一个更好的选择可能是消除枚举并要求你想要的确切忍者:
var flyingNinja = school.FlyingStudent(); // you get a FlyingNinja
flyingNinja.Fly();
在你的设计中要考虑的另一件事是:如果你想要一个可以飞的隐形忍者怎么办?还是一个还会抛出星星的武士刀忍者?这将改变您的层次结构并继承challenge your belief。
答案 3 :(得分:0)
这几乎是一种工厂方法。我会做类似的事情:
enum NinjaTypes {
Generic, Katanna, StarThrower, Invisible, Flyer
}
class Ninja {
String Name;
void jump() {
}
void kickAss() {
}
void useKatanna() {
System.out.println("nothing happens");
}
void throwStar() {
System.out.println("nothing happens");
}
void becomeInvisible() {
System.out.println("nothing happens");
}
void becomeVisible() {
System.out.println("nothing happens");
}
void fly() {
System.out.println("nothing happens");
}
void land() {
System.out.println("nothing happens");
}
}
class StarThrowerNinja extends Ninja {
void throwStar() {
System.out.println("throwing star");
}
}
class NinjaSchool {
static Ninja create(NinjaTypes WhichType) {
switch (WhichType) {
case Generic:
return new Ninja();
case StarThrower:
return new StarThrowerNinja();
default:
return null;
}
}
}
public class Main {
public static void main(String[] args) {
Ninja generic=NinjaSchool.create(NinjaTypes.Generic);
generic.throwStar();
Ninja starThrower=NinjaSchool.create(NinjaTypes.StarThrower);
starThrower.throwStar();
}
}