我在为MVVM项目设计好的架构方面遇到了问题。 我想出了类似下面的内容,请阅读并告诉我这是错误的方法还是确定: 我会有一些界面:
public interface ISomeStrategy
{
void LoadData();
void Search(string text);
IList<SomeObject> SomeObjectsList { get; set; }
}
实现此接口的类:
public class FirstStrategy: INotifyPropertyChanged, ISomeStrategy
{
public CompositePayslipItem(IDataService dataService)
{
DataService = dataService;
}
private IDataService DataService;
public IList<SomeObject> SomeObjectList{get; set;}
public async void LoadData()
{
SomeObjectList =await DataService.GetAll();
}
public async void Search(string text)
{
SomeObjectList =await DataService.GetByKey(text);
}
}
和ViewModel:
public void SomeViewModel
{
public SomeViewModel(IDataService dataService)
{
Strategy = new FirstStrategy(dataService);
Strategy.LoadData();
}
public ISomeStrategy Strategy {get; set;}
private Command<string> searchCommand;
public Command<string> SearchCommand => searchCommand?? (searchCommand= new Command(ExecuteSearchCommandAsync));
private async void ExecuteSearchCommandAsync(string text)
{
Strategy.Search(text);
}
}
正如您所看到的,所有逻辑都将出现在“策略”类中,这些类将通过ViewModel绑定到View。它给了我什么?我可以在运行时动态地更改实现。例如,如果我有一个Employee和Manager,其中搜索和获取数据的逻辑不同,我可以实现另一个类并更改属性ISomeStrategy Strategy而无需编辑Employee的现有代码(在许多方法中没有其他的)。 不幸的是,它有一些问题:
你怎么看?或者您可能使用其他模式进行业务逻辑?
编辑: Xaml部分:
<ContentPage
x:Class="Test.SomePage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<StackLayout>
<SearchBar
HeightRequest="50"
SearchCommand="{Binding SearchCommand}" />
<ListView
x:Name="formatsList"
Margin="0"
ItemsSource="{Binding Strategy.SomeObjectList}">
</StackLayout>
</ContentPage>
答案 0 :(得分:3)
试图帮助你,希望我理解你的问题:
所有绑定(命令除外)都在类 Factory中,这可能会误导:我假设您绑定到viewmodel而不是直接绑定到策略。
您应该绑定到视图模型,从那里与您的策略进行交互。否则你正在混合你的图层。
更新
据我所知,不是问题,一个典型的程序员应该能够立即发现它。
如果SomeObject是业务层中的一种模型,则会破坏图层分离参数。未来的开发者可能不会看到例如在SomeObject中重命名属性。如果SomeObject是视图模型的一部分而不是您的安全。请注意;我倾向于过度设计事物; - )
因此,您可以考虑为SomeObject
创建专用的视图模型,并使用automapper
映射到与业务相关的模型。
在大多数情况下,一个VM将具有一个策略实现,因此将会有大量代码。另一方面,将来客户端可以要求另一个角色(实现),它将更容易(只需实现另一个类 - 不编辑旧代码)。
我无法在这里找到问题或疑问。作为一般规则,使用设计模式需要先付出更多努力,以帮助您在以后处理不断变化的需求。
了解更多信息;看到这个(我的XD)帖子:ViewModels in MVC / MVVM / Seperation of layers- best practices?
有关您的代码的更多建议,免责声明:有些是基于意见的:
<小时/> 在构造函数中加载数据是不好的做法。
典型的加载操作应该是非阻塞的async
以保持UI响应。
public SomeViewModel(IDataService dataService)
{
//load data in constructor issue
Strategy.LoadData();
}
如果为null,则表示正在创建新对象。如果多个线程正在调用此属性,则可能会出现争用情况。考虑lock
(可能使用显式set方法),或在构造函数中初始化。
我认为,自从您提到 Factory 之后,这在您的代码中确实存在问题,仍然是:
调用new
使用混凝土,而不是接口。使用工厂或IoC(使用旋转变压器,即工厂)来解决此问题。
public SomeViewModel(IDataService dataService)
{
//`new` issue
Strategy = new FirstStrategy(dataService);
}
<小时/> 请勿使用
async void
首选async Task
请参阅async/await - when to return a Task vs void?
//use Task if possible
private async void ExecuteSearchCommandAsync(string text)
可能(棘手的)竞争条件
在这一行:
public Command<string> SearchCommand =>
searchCommand?? (searchCommand= new Command(ExecuteSearchCommandAsync));