我有一个类地址的实例,我必须根据环境改变:
1)Region:具有子类RegionA和RegionB的基类
2)站点:具有子类SiteA,SiteB和SiteC的基类
3)语言:具有子类LanguageA和LanguageB的基类
每个子类定义有关地址修改的约束
问题是每个元组(Region,Site,Language)都必须定义自己的修饰符。
所以,我有一个方法adjust(地址a,地区r,网站s,语言l):
void adjust(Address a, Region r, Site s, Language l){
if(r instanceof Russia && s instanceof MailRu && Language instanceof Russian){
a.set_street("abc")
}
else if(r instanceof Russia && s instanceof MailRu && Language instanceof English){
a.set_street("fgh")
}
}
在这种情况下使用的最佳设计模式是什么?
答案 0 :(得分:2)
if
和instanceof
s! Region
和Language
是(子)产品(分别是他们的工厂,当你考虑我的方式时),用于在Address
中创建街道。
package address.example;
public class AddressExample
{
public static void main(String[] args)
{
LanguageFactoryProvider lfp = new LanguageFactoryProvider.LanguageFactoryProviderImpl();
RegionFactoryProvider rfp = new RegionFactoryProvider.RegionFactoryProviderImpl();
AddressProvider provider = new AddressProvider(lfp, rfp);
Address a = provider.createAddress("RU", "USA", "Famous Street");
System.out.println(a.getStreet());
System.out.println("-----");
Address b = provider.createAddress("EN", "RUS", "Good Street");
System.out.println(b.getStreet());
}
}
输出
Address format: RU
Famous Street
USA
-----
Address format: EN
Good Street
RUS
这是地址类,你可以看到它将街道创建的部分内容委托给region
和language
(这没什么特别的,但你明白了。)
package address.example;
import address.example.LanguageFactoryProvider.Language;
import address.example.RegionFactoryProvider.Region;
public interface Address
{
public String getStreet();
static class AddressImpl implements Address
{
private final Region region;
private final Language language;
private final String street;
public AddressImpl(Region region, Language language, String street)
{
this.region = region;
this.language = language;
this.street = street;
}
@Override
public String getStreet()
{
StringBuilder sb = new StringBuilder();
sb.append(String.format("Address format: %s", language.getSpecifier()));
sb.append(String.format("%n"));
sb.append(street);
sb.append(String.format("%n"));
sb.append(region.getSpecifier());
return sb.toString();
}
}
}
这是其他使用的类。我会再次添加一些想法。
package address.example;
import address.example.LanguageFactoryProvider.Language;
import address.example.RegionFactoryProvider.Region;
public class AddressProvider
{
private final LanguageFactoryProvider lfp;
private final RegionFactoryProvider rfp;
public AddressProvider(LanguageFactoryProvider lfp, RegionFactoryProvider rfp)
{
this.lfp = lfp;
this.rfp = rfp;
}
public Address createAddress(String language, String region, String street)
{
Language _language = lfp.getLanguageFactory(language).createLanguage();
Region _region = rfp.getRegionFactory(region).createRegion();
return new Address.AddressImpl(_region, _language, street);
}
}
package address.example;
import java.util.HashMap;
import java.util.Map;
public interface LanguageFactoryProvider
{
public LanguageFactory getLanguageFactory(String language);
static interface LanguageFactory
{
public Language createLanguage();
}
static interface Language
{
public String getSpecifier();
}
static class LanguageImpl implements Language
{
private final String specifier;
public LanguageImpl(String specifier)
{
this.specifier = specifier;
}
@Override
public String getSpecifier()
{
return specifier;
}
}
static class LanguageFactoryProviderImpl implements LanguageFactoryProvider
{
private static final Map<String, LanguageFactory> factories = new HashMap<>();
static
{
factories.put("EN", new EnglishLanguageFactory());
factories.put("RU", new RussianLanguageFactory());
}
@Override
public LanguageFactory getLanguageFactory(String language)
{
if (!factories.containsKey(language))
throw new IllegalArgumentException();
LanguageFactory factory = factories.get(language);
return factory;
}
}
static class RussianLanguageFactory implements LanguageFactory
{
@Override
public Language createLanguage()
{
return new LanguageImpl("RU");
}
}
static class EnglishLanguageFactory implements LanguageFactory
{
@Override
public Language createLanguage()
{
return new LanguageImpl("EN");
}
}
}
package address.example;
import java.util.HashMap;
import java.util.Map;
public interface RegionFactoryProvider
{
public RegionFactory getRegionFactory(String region);
static interface RegionFactory
{
public Region createRegion();
}
static interface Region
{
public String getSpecifier();
}
static class RegionImpl implements Region
{
private final String specifier;
public RegionImpl(String specifier)
{
this.specifier = specifier;
}
@Override
public String getSpecifier()
{
return specifier;
}
}
static class RegionFactoryProviderImpl implements RegionFactoryProvider
{
private static final Map<String, RegionFactory> factories = new HashMap<>();
static
{
factories.put("RUS", new RussianRegionFactory());
factories.put("USA", new UsRegionFactory());
}
@Override
public RegionFactory getRegionFactory(String region)
{
if (!factories.containsKey(region))
throw new IllegalArgumentException();
RegionFactory factory = factories.get(region);
return factory;
}
}
static class RussianRegionFactory implements RegionFactory
{
@Override
public Region createRegion()
{
return new RegionImpl("RUS");
}
}
static class UsRegionFactory implements RegionFactory
{
@Override
public Region createRegion()
{
return new RegionImpl("USA");
}
}
}
答案 1 :(得分:1)
这是具有许多案例/规则的典型业务“逻辑”。为此制定声明性解决方案是值得的。
<rule>
<when category="Region" value="Russia"/>
<when category="Site" value="MailRu"/>
<action category="Address" value="abc"/>
</rule>
这允许构建诊断,完整性检查,记录未发现的案例,制作历史日志,以便将来对错误报告进行分析。
它甚至可能更具可读性。可以在一个漂亮的HTML表层次结构中转换为管理器级文档。
归结为您的代码是程序性的,无法存储所采用的控制流路径。模型驱动的方法可以缓解这种情况。 DSL是可行的,但我发现自由形式数据方法更有创意,更直接。