我试图用设计模式解决一个设计问题。既然我已经掌握了基本知识,我很肯定我已经把它复杂化了很多。我似乎有多个空接口,我可能可以用一个不同的设计少。另外,我也不确定这个项目的未来开发者是否能轻松地解决这个问题。
我做了一个班级结构的模型。该示例简化为两种服务类型(cf baseanimalservice extensions),在项目中还有更多。还有更多的基本策略实现。
首先,我想区分catservice和dogservice的上下文。这是使用basestrategy类中的一个Map来完成的,该Map将baseanimalservice作为值来启用cat/dogservice之间的多态性。根据在dog/catstrategy中实现的basestrategy的通用类型,使用不同的configurationmap,而configurationmap又根据条件的类型加载dog/catservice的一个或另一个实现。配置Map在spring.xml文件中定义。
由于dog/catservice都实现了一个额外的接口,参见someothercat/dogservice,这是我的设计之外的,dog/catservice也都有空接口。someothercatservice和someotherdogservice不相关,也不可编辑,所以我不能多态地使用它们,这就是base/cat/dogservice接口的原因。
我考虑过让basestrategy成为一个strategyfactory,它返回一个cat/dogstrategy,它反过来检查baseanimalservice要使用的标准的类型。但是由于这两种策略对它们的策略使用相同的逻辑,这意味着我必须创建另一个基类。
你怎么认为?对于这个问题有什么更好的设计建议吗?或者对现在的有什么改进?
class BaseStrategy<T extends BaseAnimalService> {
private ContextService contextService;
private Map<String, BaseAnimalService> configurationMap;
T getService() {
return configurationMap.get(contextService.getCurrentContext());
}
}
interface BaseAnimalService {
//empty
}
interface DogService extends BaseAnimalService {
//empty
}
interface CatService extends BaseAnimalService {
//empty
}
class DogStrategy extends BaseStrategy<DogService> {
//empty
}
class CatStrategy extends BaseStrategy<CatService> {
//empty
}
class BritishShortHairServiceImpl implements CatService, SomeOtherCatService {
@Override //source: SomeOtherCatService, same for other implementations below
void pur() {
//pur
}
}
class LionServiceImpl implements CatService, SomeOtherCatService {
@Override
void pur() {
//pur
}
}
class PitBullServiceImpl implements DogService, SomeOtherDogService {
@Override
void wagTail() {
//wag tail
}
}
class ChihuahuaServiceImpl implements DogService, SomeOtherDogService {
@Override
void wagTail() {
//wag tail
}
}
class CatPerson {
private BaseStrategy<CatService> catStrategy;
void pet() {
catStrategy.getService().pur();
}
}
class DogPerson {
private BaseStrategy<DogService> dogStrategy;
void feed() {
dogStrategy.getService().wagTail();
}
}
相关spring.xml片段:
<bean id="baseStrategy" abstract="true"
class="com.animals.services.BaseStrategy">
<property name="contextService" ref="contextService"/>
</bean>
<bean id="catServiceStrategy"
class="com.animals.services.CatStrategyImpl"
parent="baseStrategy">
<property name="strategyConfigurationMap">
<map>
<entry key="CONTEXT1" value-ref="britishShortHairService"/>
<entry key="CONTEXT2" value-ref="lionService"/>
</map>
</property>
</bean>
<bean id="dogServiceStrategy"
class="com.animals.services.DogStrategyImpl"
parent="baseStrategy">
<property name="strategyConfigurationMap">
<map>
<entry key="CONTEXT1" value-ref="pitbullService"/>
<entry key="CONTEXT2" value-ref="chihuahuaService"/>
</map>
</property>
</bean>
1条答案
按热度按时间guz6ccqo1#
我不熟悉spring或它的上下文服务模型,所以我从一个通用的、独立于语言的oopAngular 来处理这个问题。
在我看来,您需要考虑通过构造函数传递配置的方法(依赖注入),而不是基于Map进行切换。你需要更多的“has a”关系(合成)和更少的“is a”关系(继承)。
一
AnimalService
可以将动物对象作为构造函数的参数。我们可以说AnimalFeedbackBehavior
必须包括positiveFeedback()
,neutralFeedback()
,和negativeFeedback()
--但这些方法的实施方式因动物而异。一Cat
会吗purr()
为了回应积极的互动Dog
会吗wagTail()
.一
AnimalOwner
可以feed()
任何动物和扳机AnimalFeedbackBehavior.positiveFeedback()
. 这个AnimalOwner
不需要知道这种行为在幕后做了什么。它甚至不需要知道它有什么种类的动物。它只需要知道这个方法是存在的。typescriptPlayground链接
这里我们假设
feed
总是积极的互动。但是如果我们想让不同的动物对相同的相互作用有不同的React呢?chase()
可能对一段时间是积极的Dog
但对于一个Cat
. 阿娜ïve方法是根据Map切换反馈。但理想的设计允许最大限度地抽象AnimalOwner
不需要知道动物的种类。让我们尝试一个完全不同的设置。
如果你处理的是一小部分行为,我们可以要求动物对每种行为都有React,而不是积极/中立/消极。
但这可能会很快变得笨拙。我们可以定义一种有
respond
方法,该方法响应某种泛型操作对象。在实现中,它可以对操作做出响应,也可以忽略它。这种设置还使得多个重写行为的组合更加直观,因为我们可以通过一系列
respond
直到有人处理它。我们想知道是否有回应,所以我们需要从response
功能。如果基本上void
然后我们可以返回一个boolean
旗子那是true
如果它有React。如果响应应返回一个值,则返回该值或undefined
.这些实现目前感觉有些草率。现在他们都没用
this
所以使用class
. 但我想告诉你:两个
Animal
构成与个体行为实现AnimalBehavior
,所以AnimalOwner
我可以休息一下DogBehavior
直接或需要Animal
由一个DogBehavior
以及其他一些行为。顺序很重要。如果我们有一只吉娃娃小狗,我们需要决定
ChihuahuaBehavior
覆盖PuppyBehavior
反之亦然。typescriptPlayground链接