我试图用一个例子来理解这个干净的代码实践.考虑具有折扣开关案例的类产品.我试图用多态替换switch语句.
代码之前:
class Product {
String priceCode;
int discount;
Product(String priceCode) {
setDiscount(priceCode);
}
public int getDiscount() {
return discount;
}
public void setDiscount(String priceCode) {
switch (priceCode) {
case "CODE1":
discount = // some logic;
case "CODE2":
discount = // some other logic;
case "CODE3":
discount = // some other logic;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在下面的代码中你可以看到我删除了switch语句但是我仍然有条件来创建discountStrategy的对象.我的问题是,我仍然有条件,我试图删除多态性.
代码后:
class Product {
String priceCode;
DiscountStrategy discountStrategy;
Product(String priceCode) {
setDiscount(priceCode);
}
public int getDiscount() {
return discountStrategy.getDiscount();
}
public void setDiscount(String priceCode) …Run Code Online (Sandbox Code Playgroud) 目前,我有一堆实现Processor接口的Java类,这意味着它们都有一个processRequest(String key)方法.这个想法是每个类都有一些(比方说,<10)成员Strings,并且每个类都通过该processRequest方法映射到该类中的方法,如下所示:
class FooProcessor implements Processor
{
String key1 = "abc";
String key2 = "def";
String key3 = "ghi";
// and so on...
String processRequest(String key)
{
String toReturn = null;
if (key1.equals(key)) toReturn = method1();
else if (key2.equals(key)) toReturn = method2();
else if (key3.equals(key)) toReturn = method3();
// and so on...
return toReturn;
}
String method1() { // do stuff }
String method2() { // do other stuff }
String method3() …Run Code Online (Sandbox Code Playgroud) 我有一个搜索表单,可以在不同的提供商搜索.我开始时有一个基本控制器
public SearchController : Controller
{
protected readonly ISearchService _searchService
public SearchController(ISearchService searchService)
{
_searchService= searchService;
}
public ActionResult Search(...)
{
// Use searchService to query and return a view.
}
}
Run Code Online (Sandbox Code Playgroud)
和儿童控制器
TwitterController : SearchController
{
...
}
NewsController : SearchController
{
...
}
Run Code Online (Sandbox Code Playgroud)
我使用StructureMap在控制器中插入所有依赖项.通过此设置,我可以根据正在实例化的控制器的类型更改SearchService.
x.For<ISearchService>().ConditionallyUse(o =>
{
o.TheDefault.Is.OfConcreteType<NewsSearchService>();
o.If(c => c.ParentType == typeof(TwitterController))
.ThenIt.Is.OfConcreteType<TwitterSearchService>();
...
});
Run Code Online (Sandbox Code Playgroud)
这甚至允许我为每个控制器设置不同的视图,(只是放置相应的文件夹(Twitter,新闻......),而父控制器仍在处理所有搜索,只需简单
return View(results)
Run Code Online (Sandbox Code Playgroud)
它显示特定于推特,新闻或其他的正确视图
现在这很酷,看起来很棒,我只有一个表单,不同的视图显示在同一页面的选项卡中.这就是这种方法开始变得复杂的地方.表单必须发布到/ Twitter以在Twitter中搜索,到/新闻搜索新闻...这意味着我应该根据我的标签更改表单的操作参数,并在表单返回时显示正确的选项卡取决于..网址?疯狂随之而来.
如果你已经建立了这样的东西或知道什么是最好的方法,欢迎提出建议.
现在我认为使用表单中的参数并发布到单个控制器会减少痛苦.我正在考虑根据此参数注入正确的SearchService.什么是最好的方法?我想过使用模型活页夹,
所以我的ActionMethod看起来像这样:
public ActionResult Search(ISearchService service, Query query)
{
var results = service.Find(query);
}
Run Code Online (Sandbox Code Playgroud)
但我认为需要在ModelBinder中进行这样的调用 …
我正在寻找许多方法来实现Java中的Factory模式,但仍然找不到一个完美的方法,如果/ switch plus不使用反射,则不会受到影响.我找到的最好的一个是Tom Hawtin在这里的答案:https://stackoverflow.com/a/3434505/1390874
但我最担心的是它将匿名类的HashMap存储在内存中.
问题是除了Tom Hawtin的答案之外,人们还会考虑使用Class.newInstance()吗?这样可以避免我们在内存中存储不必要的匿名类吗?加上代码会更干净.
它看起来像这样:
class MyFactory {
private static final Map<String,Class> factoryMap =
Collections.unmodifiableMap(new HashMap<String,Class>() {{
put("Meow", Cat.class);
put("Woof", Dog.class);
}});
public Animal createAnimal(String action) {
return (Animal) factoryMap.get(action).newInstance();
}
}
Run Code Online (Sandbox Code Playgroud)