正确的程序结构(Correct program structure)
我的应用程序用于与电子设备通信。 它会读取一些识别数据(如设备固件版本),一些配置数据以及来自传感器的周期性数据。 计划分为三层:
数据层 - 描述数据如何存储在设备存储器中的简单结构。
业务层 - 用于与设备通信的类。 它们包含来自数据层的结构,并在读取和写入设备时使用它们来存储数据。
表示层 - 用户界面(WinForms); 使用businnes图层类。
假使,假设:
数据结构如下:
public struct Configuration { public int Option1; public int Option2; } public struct Visualization { public int Temperature; public int Pressure; }
业务层类包装这些结构并包含通信逻辑:
public abstract class BaseEntity<DataStructureType> { protected DataStructureType dataStructure; public BaseEntity() { this.dataStructure = new DataStructureType(); } /* device communication logic */ public abstract bool GetAllData(); } public class ConfigurationEntity : BaseEntity<Configuration> { public override bool GetAllData() { //getting configuration data from device } public int Option1 { get { return this.dataStructure.Option1; } set { this.dataStructure.Option1 = value; } } public int Option2; { get { return this.dataStructure.Option2 * 100; } set { this.dataStructure.Option1 = value / 100; } } } public class VisualizationEntity : BaseEntity<Visualization> { public override bool GetAllData() { //getting visualization data from device } public int Temperature { get { return this.dataStructure.temperature; } } public float Pressure; { get { return Conversions.IntToPressure(this.dataStructure.pressure); } } }
和Conversions类用于转换二进制数据:
public static class Conversions { public static float IntToPressure(int parameter) { return PressureAlgorithmA(parameter); } private static float PressureAlgorithmA(int parameter) { //some algorithm (called A) to convert binary pressure to pressure in bars } }
问题是新的固件版本,因为应用程序应该处理两个设备版本(旧版本和更新版本)。 新版本已更新,包括几个新结构,新转换算法,新配置选项。 看起来像:
public struct Configuration { /* old options are here */ //and updated goes here: public int Option3; public int Option4; } public class ConfigurationEntity : BaseEntity<Configuration> { /* old code is here */ //and updated goes here public int Option3 { get { return this.dataStructure.Option3; } set { this.dataStructure.Option3 = value; } } public int Option4; { get { return this.dataStructure.Option4 * 20; } set { this.dataStructure.Option4 = value / 20; } } }
转换也改变了:
public static class Conversions { public static float IntToPressure(int parameter) { return PressureAlgorithmB(parameter); } private static float PressureAlgorithmB(int parameter) { //some algorithm (called B) to convert binary pressure to pressure in bars } }
现在我每次需要使用新功能时都要检查设备版本(当从Configuration更改Option3或Option4时,或者当我需要使用新数据etities或在向用户显示压力时使用哪种算法)。
我的问题是如何使用OOP实践来做到这一点? 在C#中执行此操作的正确方法是什么?
我在考虑工厂模式,但配置中的新选项或新数据实体是什么?
My application is used for communication with electronic device. It reads some identification data (like device firmware version), some configuration data, and periodically data from sensors. Program is divided into three layers:
Data layer - simple structures describing how data are stored in device memory.
Business layer - classes used for communication with device. They contains structures from data layer and using them to store data when reading from and writing to device.
Presentation layer - user interface (WinForms); using businnes layer classes.
Assume that:
Data structures looks like:
public struct Configuration { public int Option1; public int Option2; } public struct Visualization { public int Temperature; public int Pressure; }
Business layer classes wraps these structures and contains logic for communication:
public abstract class BaseEntity<DataStructureType> { protected DataStructureType dataStructure; public BaseEntity() { this.dataStructure = new DataStructureType(); } /* device communication logic */ public abstract bool GetAllData(); } public class ConfigurationEntity : BaseEntity<Configuration> { public override bool GetAllData() { //getting configuration data from device } public int Option1 { get { return this.dataStructure.Option1; } set { this.dataStructure.Option1 = value; } } public int Option2; { get { return this.dataStructure.Option2 * 100; } set { this.dataStructure.Option1 = value / 100; } } } public class VisualizationEntity : BaseEntity<Visualization> { public override bool GetAllData() { //getting visualization data from device } public int Temperature { get { return this.dataStructure.temperature; } } public float Pressure; { get { return Conversions.IntToPressure(this.dataStructure.pressure); } } }
And Conversions class used to convert binary data:
public static class Conversions { public static float IntToPressure(int parameter) { return PressureAlgorithmA(parameter); } private static float PressureAlgorithmA(int parameter) { //some algorithm (called A) to convert binary pressure to pressure in bars } }
Problem is new firmware version, because application should handle both device versions(older and newer). New version has been updated with couple of new structures to read, new conversion algorithms, new configuration options. It looks like:
public struct Configuration { /* old options are here */ //and updated goes here: public int Option3; public int Option4; } public class ConfigurationEntity : BaseEntity<Configuration> { /* old code is here */ //and updated goes here public int Option3 { get { return this.dataStructure.Option3; } set { this.dataStructure.Option3 = value; } } public int Option4; { get { return this.dataStructure.Option4 * 20; } set { this.dataStructure.Option4 = value / 20; } } }
Also Conversions has beem changed:
public static class Conversions { public static float IntToPressure(int parameter) { return PressureAlgorithmB(parameter); } private static float PressureAlgorithmB(int parameter) { //some algorithm (called B) to convert binary pressure to pressure in bars } }
Now I have to check for device version every time I need to use new funcionality (when changing Option3 or Option4 from Configuration or when I need to use new data etities or which algorithm use when showing pressure to user).
My question is how can I do that with OOP practicies? What is correct way to do this in C#?
I was thinking about factory pattern, but what with new options in Configuration, or with new data entities?
原文:https://stackoverflow.com/questions/10190781
最满意答案
将相同的样式应用于
UIButton
多个实例:
严格的程序化路线:
前两种方法就是我要做的。 第三个是为了说明可以编写一个从另一个按钮复制设置的
init
。使用子类应用预设样式:
class StyledButton : UIButton { override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.blackColor() // more styling } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
将预设样式应用于UIButton的扩展名:
extension UIButton { func setCustomStyle1() { self.backgroundColor = UIColor.blackColor() // nore styling } }
在UIButton的扩展中使用便利init复制样式:
extension UIButton { convenience init(styleFromButton button: UIButton, frame: CGRect) { self.init(frame: frame) self.backgroundColor = button.backgroundColor } }
Interface Builder解决方案:
创建一个新的Swift文件:
在新文件中创建
UIButton
的子类:class StyledButton : UIButton { override init(frame: CGRect) { super.init(frame: frame) style() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) style() } private func style() { self.backgroundColor = UIColor.blackColor() // more styling } }
返回Interface Builder并选择要设置样式的
UIButton
。 选择右侧的第三个面板,这是身份检查器 。 选择子类作为UIButton
的类。重复所有按钮以设置样式。
或者在IB和Alt-Drag中设置整个内容的样式以制作副本。
Applying the same style to multiple instances of
UIButton
:
Strictly Programmatic route:
The first two methods are what I would do. The third is only to illustrate that it is possible to write an
init
that copies settings from another button.Apply preset style with a sub class:
class StyledButton : UIButton { override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.blackColor() // more styling } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Apply preset style with an extension to UIButton:
extension UIButton { func setCustomStyle1() { self.backgroundColor = UIColor.blackColor() // nore styling } }
Copy style with a convenience init in an extension to UIButton:
extension UIButton { convenience init(styleFromButton button: UIButton, frame: CGRect) { self.init(frame: frame) self.backgroundColor = button.backgroundColor } }
Interface Builder solution:
Create a new Swift file:
Create a sub class of
UIButton
in the new file:class StyledButton : UIButton { override init(frame: CGRect) { super.init(frame: frame) style() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) style() } private func style() { self.backgroundColor = UIColor.blackColor() // more styling } }
Go back to the Interface Builder and select a
UIButton
you want to style. Select the third panel on the right, this is the identity inspector. Select your sub class as the class for theUIButton
.Repeat for all buttons to style.
Or style the entire thing in IB and Alt-Drag to make a copy.
相关问答
更多-
将相同的样式应用于UIButton多个实例: 严格的程序化路线: 前两种方法就是我要做的。 第三个是为了说明可以编写一个从另一个按钮复制设置的init 。 使用子类应用预设样式: class StyledButton : UIButton { override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.blackColor() ...
-
您无法从方法返回异步结果,而是需要使用回调。 // categoryDao.js var Category = mongoose.model('Category'); exports.allCategories = function(callback) { Category.find().exec(function(err, categories) { console.log(categories); // Deliver the results to the ca ...
-
您可以使用某种方法创建工厂,例如clearColoredContent在两个控制器中注入此工厂,并将所需的范围传递给此。 app.factory('Utility', function(){ return { clearColoredContent: function(scope){ scope.coloredContent = []; } } }) 并像这样使用它 app.controller('View2Cntr', ['$sco ...
-
对于数据层 ,我认为最好的方法是使用服务 。 您可以使用服务在不同控制器之间传递数据。 您需要做的就是使用依赖注入将服务注入适当的控制器。 并且在每个服务中都有getter和setter来存储和检索数据。 至于组织,每个视图应该有自己的控制器。 对于视图层 ,最好的选择是自定义指令 指令是可重用的组件 ,可在整个应用程序中使用,并可以在HTML中的任何位置注入。 每个可重用的指令都可以通过属性将数据传递给它来定制。 For the data layer, I think the best way would ...
-
在多个视图控制器中轻松重用一堆代码的最佳做法是什么?(What's best practice to easily reuse bunch of code in multiple view controllers?)[2022-02-22]
Objective-C提供了两种重用代码的一般方法: 继承一个基类,和 使用共享功能。 第一种情况很简单:如果您需要多个视图控制器中的特定功能,请使用共享方法创建基本视图控制器,然后从中派生其他视图控制器: @interface BaseViewController : UIViewController -(void)sharedMethodOne; -(void)sharedMethodTwo; @end @interface FirstViewController : BaseViewControlle ... -
MMDrawerController并实例化许多视图控制器(MMDrawerController and instantiating many view controllers)[2023-11-18]
这种方法对我来说效果很好,每次用户更改视图时都不需要实例化新的视图控制器或导航控制器。 声明一个可变数组来保存导航控制器: @property (nonatomic, strong) NSMutableArray *navigationControllerArray; 使用与视图控制器相同数量的空字符串初始化并填充数组: - (void)viewDidLoad { [super viewDidLoad]; self.navigationControllerArray = [[NSMuta ... -
诚然,这是个人偏好和经验的问题。 例如,看似务实的方法是在div上使用.white-box类; 它非常简单,无需进口! 稍后,您决定其他控件中的每个白盒都需要更多的阴影 ,所以你去为.some-component .white-box和bam添加CSS规则,现在你有一个阴影'没有搞乱原始CSS类的ier白盒子。 好,易于! 问题是,当你做一次或两次时,没关系。 但是你很快就养成了为特定目的“修补”课程名称规则的习惯,在你知道之前你就是在不知情的情况下混合规则,这正是它所说的: 层叠式样式表。 我自己去过那里 ...
-
没有人回答,所以,我试试。 看起来,没有办法在故事板中的几个场景之间共享相同的调整。 通过创建viewControllers的自定义子类并在其代码中设置调整甚至可以在appDelegate中调整外观,并为某些人提供外观属性,可以共享相同的内容。 例如,如果你想在一个地方为你的所有应用程序的导航控制器设置色彩颜色,你最好在AppDelegate里面做它 application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDict ...
-
xcode - ios - 如何最有效地重用视图控制器?(xcode - ios - How to most effectively reuse view controllers? [closed])[2020-03-03]
用包含上述所有选项的UIView创建一个.xib文件。 使用UIView子类创建一个Objective-C类,并将此类映射到上面的.xib文件。 为所有UI元素生成IBouteLets并使这些IBoutlet的范围成为全局(即在.h文件中声明它们) 在这个类中添加UITextView / UITextField等的所有委托方法 从任何视图控制器,当你想添加这个视图到控制器的视图 NSArray * array = [[NSBundle mainBundle] loadNibNamed:@"CustomVie ... -
如果您需要单独的路由,但需要相同的控制器,但有一些选项,则可以使用路由定义中的resolve选项来传递一些选项: $routeProvider. when('/users', { templateUrl: '/partials/table.html', controller: 'TableController', resolve: { 'option1': function() { return 'val1' }, 'option2': functi ...