从抽象工厂获得专业化 class
Get specialized class from Abstract Factory
我有三个 classes,AbstractContext、ContextA 和 ContextB,我想在创建方面进行概括,但我想在不同的上下文中访问每个方法的特定方法。
抽象上下文:
public abstract class AbstractContext {
public abstract void print();
}
上下文A:
public class ContextA extends AbstractContext {
@Override
public void print() {
System.out.println("In context A");
}
public void doSomeA(){
System.out.println("Do some A");
}
}
上下文 B:
public class ContextB extends AbstractContext {
@Override
public void print() {
}
public void doSomeB(){
int a=1;
System.out.println(a);
}
}
我实现了抽象工厂模式,因此我可以概括这些 classes 的创建:
抽象工厂:
public abstract class AbstractFactory {
public abstract AbstractContext createContext();
}
工厂A:
public class FactoryA extends AbstractFactory {
@Override
public AbstractContext createContext() {
AbstractContext newClass = new ContextA();
return newClass;
}
}
工厂 B
public class FactoryB extends AbstractFactory {
@Override
public AbstractContext createContext() {
AbstractContext newClass = new ContextB();
return newClass;
}
}
工厂制造商
public class FactoryMaker {
private static AbstractFactory factory = null;
public static AbstractFactory getFactory(String condition) {
if (condition == "A") {
factory = new FactoryA();
} else {
factory = new FactoryB();
}
return factory;
}
}
这里的问题是,创建一个实例后,由于所有工厂return基类型我无法访问每个子class的任何具体方法class。
public class Main {
public static void main(String[] args) {
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
contextA.print(); //Works fine
contextA.doSomeA(); //Won't compile
AbstractContext contextB = FactoryMaker.getFactory("").createContext();
contextB.print(); //Works fine
contextB.doSomeB(); //Won't Compile
}
}
第一次尝试时,我尝试创建具有相同签名的方法来接受 class 的不同子类型,但随后出现编译错误,因为基类型与方法期望的具体类型不匹配:
public static void process(ContextA context){
context.doSomeA();
}
public static void process(ContextB context){
context.doSomeB();
}
有没有办法实现我想要做的事情?
为了给你一个额外的上下文,我正在创建一个 Java 共享库 (API),它将被其他开发人员使用,我正在尝试做的是找到一种方法开发人员可以从我的 API 那里以标准方式获得他们想要的上下文。
我希望他们请求上下文并从那时起工作,填充每个上下文具有的属性,然后 api 将处理每个上下文的特定部分。
编辑:
看来我应该给你更多的细节。
假设我有两个 Web 应用程序,这两个 Web 应用程序访问相同的服务业务 classes,但可能有不同的业务规则,因为两个不同的 companies.Each 公司有相同产品的变体。
我想要实现的目标是制作一个 API 内部将为开发人员提供繁重的通用代码。
我不希望开发人员做的是告诉 api 例如产品和公司,以及 api return 正确的上下文并根据业务规则。
我希望他们 "almost" 构建一个 gui 来填充我正在 return 的每个上下文。
当然,他们需要知道他们使用的上下文,以便在 GUI 和上下文 i return 之间进行绑定,但与此同时,他们的 GUI 可以有共同点UI 份。
我也在更新内容,目前,我所做的是创建一个 ContextHolder,return 是开发人员想要的上下文,但它看起来不太好,因为公司可以扩展产品线或每种产品的变体。
我给出了使用不同方法的 abstractContext 的不同实现的例子,因为在每个上下文中我都需要访问特定的属性(最终将是同一件事,属性是方法 returning 数据).最后,contexts 只会旧不同的数据集,公共数据将留在 abstractContext class.
我正在尽力解释自己,如果不够清楚,请告诉我。
可能是变体:
public interface Context {
void print();
}
public class ContextHolder<T extends Context> {
private T context;
public ContextHolder(T context) {
this.context = context;
}
public T getContext() {
return context;
}
public void print() {
context.print();
}
public void foo() {
}
}
public class ContextA implements Context {
@Override
public void print() {
System.out.println("In context A");
}
public void doSomeA() {
System.out.println("Do some A");
}
}
public class ContextB implements Context {
@Override
public void print() {
}
public void doSomeB() {
int a = 1;
System.out.println(a);
}
}
public abstract class AbstractFactory<T extends Context> {
public abstract ContextHolder<T> createContext();
}
public class FactoryA extends AbstractFactory<ContextA> {
@Override
public ContextHolder<ContextA> createContext() {
return new ContextHolder<ContextA>(new ContextA());
}
}
public class FactoryB extends AbstractFactory<ContextB> {
@Override
public ContextHolder<ContextB> createContext() {
return new ContextHolder<ContextB>(new ContextB());
}
}
public class FactoryMaker {
private static AbstractFactory factory = null;
public static AbstractFactory getFactory(String condition) {
if (condition == "A") {
factory = new FactoryA();
} else {
factory = new FactoryB();
}
return factory;
}
}
public static void main(String[] args) {
ContextHolder<ContextA> contextHolderA = FactoryMaker.getFactory("A").createContext();
contextHolderA.print();
contextHolderA.getContext().doSomeA();
ContextHolder<ContextB> contextHolderB = FactoryMaker.getFactory("").createContext();
contextHolderB.print();
contextHolderB.getContext().doSomeB();
}
我认为你的设计有问题。工厂returns一个AbstractContext
,但显然这种类型对客户来说是不够的。我建议重新考虑 AbstractContext
API 或引入一个接口。在这两种情况下,您都必须为两种上下文找到一个摘要 api。
否则....如果你不能那样做,你必须通过使用
来重建丢失的类型信息
- Visitor Pattern
- 适配器模式
访问者模式方法
public interface ContextVisitor {
public void visit(ContextA contextA);
public void visit(ContextB contextB);
}
public abstract class AbstractContext {
public abstract void print();
public abstract void accept(ContextVisitor contextVisitor);
}
public class ContextA extends AbstractContext {
....
public void accept(ContextVisitor contextVisitor){
contextVisitor.visit(this);
}
}
模式用法
ContextVisitor cv = new ContextVisitor(){
public void visit(ContextA contextA){
contextA.print();
contextA.doSomeA();
}
public void visit(ContextB contextB){
contextB.print();
contextB.doSomeB();
}
}
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
contextA.accept(cv);
AbstractContext contextB = FactoryMaker.getFactory("").createContext();
contextB.accept(cv);
适配器模式方法
public abstract class AbstractContext {
public abstract void print();
public abstract <T extends AbstractContext> T getAdapter(Class<T> type);
}
public class ContextA extends AbstractContext {
....
public <T extends AbstractContext> T getAdapter(Class<T> type) {
if(type.isInstance(this)){
return type.cast(this);
}
return null;
}
}
适配器模式用法:
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
ContextA contextA = contextA.getAdapter(ContextA.class);
if(contextA != null){
contextA.print();
contextA.doSomeA();
}
如果这两种方法都不适用于您的情况,您只能使用 instanceof
检查和强制转换来重建丢失的类型信息。但这不是首选方式,因为您将类型选择移至客户端代码,并且如果更改继承层次结构,它可能会很快被破坏。
我认为你为这项工作选择了一个过于复杂的工具。
如果只是想"guarantee each context is initialized the same way, and not having the developers to make the different initilization themselves",封装就够了
这个基本的面向对象原则允许您将实现细节隐藏在一个对象中,这似乎正是您所需要的。
假设ContextA
仍然扩展AbstractContext
,比较这个(1)
ContextA contextA = new ContextA();
contextA.print(); //Works fine
contextA.doSomeA(); //Works fine
使用您之前的代码 (2)
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
contextA.print(); //Works fine
contextA.doSomeA(); //Won't compile
请告诉我们 (2) 中有哪些是您无法通过 (1) 实现的,因为在您的问题和示例的当前状态下,我看不到它。
我有三个 classes,AbstractContext、ContextA 和 ContextB,我想在创建方面进行概括,但我想在不同的上下文中访问每个方法的特定方法。
抽象上下文:
public abstract class AbstractContext {
public abstract void print();
}
上下文A:
public class ContextA extends AbstractContext {
@Override
public void print() {
System.out.println("In context A");
}
public void doSomeA(){
System.out.println("Do some A");
}
}
上下文 B:
public class ContextB extends AbstractContext {
@Override
public void print() {
}
public void doSomeB(){
int a=1;
System.out.println(a);
}
}
我实现了抽象工厂模式,因此我可以概括这些 classes 的创建:
抽象工厂:
public abstract class AbstractFactory {
public abstract AbstractContext createContext();
}
工厂A:
public class FactoryA extends AbstractFactory {
@Override
public AbstractContext createContext() {
AbstractContext newClass = new ContextA();
return newClass;
}
}
工厂 B
public class FactoryB extends AbstractFactory {
@Override
public AbstractContext createContext() {
AbstractContext newClass = new ContextB();
return newClass;
}
}
工厂制造商
public class FactoryMaker {
private static AbstractFactory factory = null;
public static AbstractFactory getFactory(String condition) {
if (condition == "A") {
factory = new FactoryA();
} else {
factory = new FactoryB();
}
return factory;
}
}
这里的问题是,创建一个实例后,由于所有工厂return基类型我无法访问每个子class的任何具体方法class。
public class Main {
public static void main(String[] args) {
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
contextA.print(); //Works fine
contextA.doSomeA(); //Won't compile
AbstractContext contextB = FactoryMaker.getFactory("").createContext();
contextB.print(); //Works fine
contextB.doSomeB(); //Won't Compile
}
}
第一次尝试时,我尝试创建具有相同签名的方法来接受 class 的不同子类型,但随后出现编译错误,因为基类型与方法期望的具体类型不匹配:
public static void process(ContextA context){
context.doSomeA();
}
public static void process(ContextB context){
context.doSomeB();
}
有没有办法实现我想要做的事情?
为了给你一个额外的上下文,我正在创建一个 Java 共享库 (API),它将被其他开发人员使用,我正在尝试做的是找到一种方法开发人员可以从我的 API 那里以标准方式获得他们想要的上下文。 我希望他们请求上下文并从那时起工作,填充每个上下文具有的属性,然后 api 将处理每个上下文的特定部分。
编辑: 看来我应该给你更多的细节。
假设我有两个 Web 应用程序,这两个 Web 应用程序访问相同的服务业务 classes,但可能有不同的业务规则,因为两个不同的 companies.Each 公司有相同产品的变体。
我想要实现的目标是制作一个 API 内部将为开发人员提供繁重的通用代码。
我不希望开发人员做的是告诉 api 例如产品和公司,以及 api return 正确的上下文并根据业务规则。
我希望他们 "almost" 构建一个 gui 来填充我正在 return 的每个上下文。 当然,他们需要知道他们使用的上下文,以便在 GUI 和上下文 i return 之间进行绑定,但与此同时,他们的 GUI 可以有共同点UI 份。
我也在更新内容,目前,我所做的是创建一个 ContextHolder,return 是开发人员想要的上下文,但它看起来不太好,因为公司可以扩展产品线或每种产品的变体。
我给出了使用不同方法的 abstractContext 的不同实现的例子,因为在每个上下文中我都需要访问特定的属性(最终将是同一件事,属性是方法 returning 数据).最后,contexts 只会旧不同的数据集,公共数据将留在 abstractContext class.
我正在尽力解释自己,如果不够清楚,请告诉我。
可能是变体:
public interface Context {
void print();
}
public class ContextHolder<T extends Context> {
private T context;
public ContextHolder(T context) {
this.context = context;
}
public T getContext() {
return context;
}
public void print() {
context.print();
}
public void foo() {
}
}
public class ContextA implements Context {
@Override
public void print() {
System.out.println("In context A");
}
public void doSomeA() {
System.out.println("Do some A");
}
}
public class ContextB implements Context {
@Override
public void print() {
}
public void doSomeB() {
int a = 1;
System.out.println(a);
}
}
public abstract class AbstractFactory<T extends Context> {
public abstract ContextHolder<T> createContext();
}
public class FactoryA extends AbstractFactory<ContextA> {
@Override
public ContextHolder<ContextA> createContext() {
return new ContextHolder<ContextA>(new ContextA());
}
}
public class FactoryB extends AbstractFactory<ContextB> {
@Override
public ContextHolder<ContextB> createContext() {
return new ContextHolder<ContextB>(new ContextB());
}
}
public class FactoryMaker {
private static AbstractFactory factory = null;
public static AbstractFactory getFactory(String condition) {
if (condition == "A") {
factory = new FactoryA();
} else {
factory = new FactoryB();
}
return factory;
}
}
public static void main(String[] args) {
ContextHolder<ContextA> contextHolderA = FactoryMaker.getFactory("A").createContext();
contextHolderA.print();
contextHolderA.getContext().doSomeA();
ContextHolder<ContextB> contextHolderB = FactoryMaker.getFactory("").createContext();
contextHolderB.print();
contextHolderB.getContext().doSomeB();
}
我认为你的设计有问题。工厂returns一个AbstractContext
,但显然这种类型对客户来说是不够的。我建议重新考虑 AbstractContext
API 或引入一个接口。在这两种情况下,您都必须为两种上下文找到一个摘要 api。
否则....如果你不能那样做,你必须通过使用
来重建丢失的类型信息- Visitor Pattern
- 适配器模式
访问者模式方法
public interface ContextVisitor {
public void visit(ContextA contextA);
public void visit(ContextB contextB);
}
public abstract class AbstractContext {
public abstract void print();
public abstract void accept(ContextVisitor contextVisitor);
}
public class ContextA extends AbstractContext {
....
public void accept(ContextVisitor contextVisitor){
contextVisitor.visit(this);
}
}
模式用法
ContextVisitor cv = new ContextVisitor(){
public void visit(ContextA contextA){
contextA.print();
contextA.doSomeA();
}
public void visit(ContextB contextB){
contextB.print();
contextB.doSomeB();
}
}
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
contextA.accept(cv);
AbstractContext contextB = FactoryMaker.getFactory("").createContext();
contextB.accept(cv);
适配器模式方法
public abstract class AbstractContext {
public abstract void print();
public abstract <T extends AbstractContext> T getAdapter(Class<T> type);
}
public class ContextA extends AbstractContext {
....
public <T extends AbstractContext> T getAdapter(Class<T> type) {
if(type.isInstance(this)){
return type.cast(this);
}
return null;
}
}
适配器模式用法:
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
ContextA contextA = contextA.getAdapter(ContextA.class);
if(contextA != null){
contextA.print();
contextA.doSomeA();
}
如果这两种方法都不适用于您的情况,您只能使用 instanceof
检查和强制转换来重建丢失的类型信息。但这不是首选方式,因为您将类型选择移至客户端代码,并且如果更改继承层次结构,它可能会很快被破坏。
我认为你为这项工作选择了一个过于复杂的工具。
如果只是想"guarantee each context is initialized the same way, and not having the developers to make the different initilization themselves",封装就够了
这个基本的面向对象原则允许您将实现细节隐藏在一个对象中,这似乎正是您所需要的。
假设ContextA
仍然扩展AbstractContext
,比较这个(1)
ContextA contextA = new ContextA();
contextA.print(); //Works fine
contextA.doSomeA(); //Works fine
使用您之前的代码 (2)
AbstractContext contextA = FactoryMaker.getFactory("A").createContext();
contextA.print(); //Works fine
contextA.doSomeA(); //Won't compile
请告诉我们 (2) 中有哪些是您无法通过 (1) 实现的,因为在您的问题和示例的当前状态下,我看不到它。