Implement Derived Class as Base on Constructor Exception? - c#

I'm working with code to implement a hardware test system, which involves communication with several benchtop instruments. When I instantiate an instance of one of these instruments, the constructor attempts to open the communication session with the instrument. If that fails, I can throw all kinds of errors, but what I'd like to do is to have the instrument object default to a virtual or simulation mode where no actual communication is done but I can still run my code.
Right now I have all instruments of one type inheriting from a base class. I've added virtual methods to the base class which perform these debugging functions, but I'm stuck on a clean way to modify the derived object at creation time to implement the base classes methods when the communication session fails.
The ideal solution would be to have the constructor (technically the new keyword) return an instance of the base class instead of the derived class, but I've done a fair amount of searching and that doesn't appear to be possible.
I could add a property to the derived class to use as a boolean flag where every method in the derived class tests against that flag and invokes the base class method if true, but I'm hoping to find a more elegant solution that doesn't require a few hundred if statements and a serious flogging of base.Stuff() calls.
I have a few dozen methods and a handful of instruments inheriting in this way so a solution that doesn't require an explicit change to every one of those overriding methods would go a long, long way.
public abstract class BaseInstrument
{
public string Address;
protected MessageBasedSession MbSession;
public virtual string Identify()
{
return "Debugging mode, fake identity";
}
}
public class SpecificInstrument : BaseInstrument
{
public SpecificInstrument(string address)
{
Address = address;
try
{
MbSession = (MessageBasedSession)ResourceManager.GetLocalManager().Open(Address);
}
catch
{
// Return an object modified in such a way that it invokes base class virtual methods
// instead of method overrides.
// Constructor has no return value (that comes from the new keyword) so I can't
// just return an instance of the base class...
}
}
public override string Identify()
{
return ActualInstrumentRead();
}
// ...
}
public class Program
{
public static void Main()
{
SpecificInstrument instr = new SpecificInstrument(ipAddress);
Console.WriteLine(instr.Identify()); // Would like to print the debug case if eg. my LAN is down
}
}
I feel like I might be missing an obvious solution to this but I've been scratching my head for hours.

You can't return a BaseInstrument from a SpecificInstrument constructor.
One alternative would be to put this logic where you create this instrument:
BaseInstrument instrument;
try {
instrument = new SpecificInstrument();
}
catch {
instrument = new BaseInstrument();
}

Related

Refactoring to make code open for extensions but closed for modifications

For my project purpose I need to send metrics to AWS.
I have main class called SendingMetrics.
private CPUMetric _cpuMetric;
private RAMMetric _ramMetric;
private HDDMetric _hddMetric;
private CloudWatchClient _cloudWatchClient(); //AWS Client which contains method Send() that sends metrics to AWS
public SendingMetrics()
{
_cpuMetric = new CPUMetric();
_ramMetric = new RAMMetric();
_hddMetric = new HDDMetric();
_cloudwatchClient = new CloudwatchClient();
InitializeTimer();
}
private void InitializeTimer()
{
//here I initialize Timer object which will call method SendMetrics() each 60 seconds.
}
private void SendMetrics()
{
SendCPUMetric();
SendRAMMetric();
SendHDDMetric();
}
private void SendCPUMetric()
{
_cloudwatchClient.Send("CPU_Metric", _cpuMetric.GetValue());
}
private void SendRAMMetric()
{
_cloudwatchClient.Send("RAM_Metric", _ramMetric.GetValue());
}
private void SendHDDMetric()
{
_cloudwatchClient.Send("HDD_Metric", _hddMetric.GetValue());
}
Also I have CPUMetric, RAMMetric and HDDMetric classes that looks pretty much similar so I will just show code of one class.
internal sealed class CPUMetric
{
private int _cpuThreshold;
public CPUMetric()
{
_cpuThreshold = 95;
}
public int GetValue()
{
var currentCpuLoad = ... //logic for getting machine CPU load
if(currentCpuLoad > _cpuThreshold)
{
return 1;
}
else
{
return 0;
}
}
}
So the problem I have is that clean coding is not satisfied in my example. I have 3 metrics to send and if I need to introduce new metric I will need to create new class, initialize it in SendingMetrics class and modify that class and that is not what I want. I want to satisfy Open Closed principle, so it is open for extensions but closed for modifications.
What is the right way to do it? I would move those send methods (SendCPUMetric, SendRAMMetric, SendHDDMetric) to corresponding classes (SendCPUMetric method to CPUMetric class, SendRAMMEtric to RAMMetric, etc) but how to modfy SendingMetrics class so it is closed for modifications and if I need to add new metric to not change that class.
In object oriented languages like C# the Open Closed Principle (OCP) is usually achieved by using the concept of polymorphism. That is that objects of the same kind react different to one and the same message. Looking at your class "SendingMetrics" it's obvious that the class works with different types of "Metrics". The good thing is that your class "SendingMetrics" talks to a all types of metrics in the same way by sending the message "getData". Hence you can introduce a new abstraction by creating an Interface "IMetric" that is implemented by the concrete types of metrics. That way you decouple your "SendingMetrics" class from the concrete metric types wich means the class does not know about the specific metric types. It only knows IMetric and treats them all in the same way wich makes it possible to add any new collaborator (type of metric) that implements the IMetric interface (open for extension) without the need to change the "SendingMetrics" class (closed for modification). This also requires that the objects of the different types of metrics are not created within the "SendingMetrics" class but e.g. by a factory or outside of the class and being injected as IMetrics.
In addition to using inheritance to enable polymorphism and achiving OCP by introducing the interface IMetric you can also use inheritance to remove redundancy. Which means you can introduce an abstract base class for all metric types that implements common behaviour that is used by all types of metrics.
Your design is almost correct. You got 3 data retriever and 1 data sender. So it's easy to add more metric (more retriever) (open for extensions) without affecting current metrics (closed for modifications), you just need a bit more refactor to reduce duplicated code.
Instead of have 3 metrics classes look very similar. Only below line is different
var currentCpuLoad = ... //logic for getting machine CPU load
You can create a generic metric like this
internal interface IGetMetric
{
int GetData();
}
internal sealed class Metric
{
private int _threshold;
private IGetMetric _getDataService;
public Metric(IGetMetric getDataService)
{
_cpuThreshold = 95;
_getDataService = getDataService;
}
public int GetValue()
{
var currentCpuLoad = _getDataService.GetData();
if(currentCpuLoad > _cpuThreshold)
{
return 1;
}
else
{
return 0;
}
}
}
Then just create 3 GetMetric classes to implement that interface. This is just 1 way to reduce the code duplication. You can also use inheritance (but I don't like inheritance). Or you can use a Func param.
UPDATED: added class to get CPU metric
internal class CPUMetricService : IGetMetric
{
public int GetData() { return ....; }
}
internal class RAMMetricService : IGetMetric
{
public int GetData() { return ....; }
}
public class AllMetrics
{
private List<Metric> _metrics = new List<Metric>()
{
new Metric(new CPUMetricService());
new Metric(new RAMMetricService());
}
public void SendMetrics()
{
_metrics.ForEach(m => ....);
}
}

Not sure with my approach in .net application

once again I'm here for help. I'm writing my first "real-like" application to practice what I learned and I am not sure about my approach. I'll try to explain it as best as my english allows me.
Application consist of base abstract class and three classes inherited from that base.
abstract class BaseClass
{
// Some stuff...
// This method is used in all classes. It gets whole adb output
// and returns it as a string for future formating
protected string ProcessAdbCommand(string command)
{
try
{
_processInfo.Arguments = command;
Process adbProcess = Process.Start(_processInfo);
adbProcess.WaitForExit();
return adbProcess.StandardOutput.ReadToEnd();
}
catch (Exception e)
{
WriteToLog(e.Message);
return null;
}
}
}
After ProcessAdbCommand returns output, I will call another method which handles output as needed. Principle is always the same - format output and make somethinkg usefull based on the output.
Now I'd like to make clear, that method responsible for output handling needs to be in every inherited class. But problem is that in very class it returns different value type (boolean, List of IDevice and strings)
I am struggling here. First I wanted to make it protected abstract. Somethink like
abstract class BaseClass
{
// Some stuff...
// Same as above
protected string ProcessAdbCommand(string command)
{
//Same as above
}
//Method which will be implemented in every inherited class differently
protected bool|List<IDevice>|string ProcessAdbOutput(string adbOutput)
{
//Method implementation
return bool|List<IDevice>|string
}
}
But as I discovered it is not possible to override return type. And because method will be always used only internally in classes, I do not see reason to "force" it using interfaces.
After some time I game up and decided to forget about forcing implementation in derived classes and simply write them as I need. But do you think it is "legal" approach? How would you solve problem like that in "real world" application? Is there something I am still missing or is my approach simply wrong? Thank you.
Struggling Greenhorn.
One possible approach would be to make the abstract base class generic and accept a T parameter, which can also be the output of your ProcessAdbOutput method. Then, you make the method abstract to make sure any derived type has to implement it:
public abstract class BaseClass<T>
{
protected string ProcessAdbCommand(string command)
{
return string.Empty;
}
public abstract T ProcessAdbOutput(string result);
}
public class DerivedClass : BaseClass<IList<IDevice>>
{
public override IList<IDevice> ProcessAdbOutput(string result)
{
return new List<IDevice>();
}
}

How to determine the type of an object and pass it as an argument to a method?

My application contains one base class called Statistic and three classes which inherit from it: LSP, CPU, Memory. I also have an additional class called ExecuteRequest whose constructor takes either an instance of Statistic or one of the more derived types (LSP, CPU or Memory). What I want to do is: determine what type of object it is (whether LSP, CPU or Memory).
To accomplish this, I created the DeterminateKpiType method which would check the incoming Statistic instance and cast it to a specific property of that type. Once complete, this specific object will be passed to the RunRequest() method. Unfortunately I encountered a problem while attempting to solve this.
I received errors (when invoking DeterminateKpiType()) saying that it cannot return those types and I have no clue how to pass the object to the RunRequest() method. How can I achieve this result? If something is unclear feel free to revert/ask.
Here is the code listing:
class ExecuteRequest
{
public Statistic KPI { get; set; }
public LSP LSP { get; set; }
public CPU CPU { get; set; }
public Memory Memory { get; set; }
public ExecuteRequest(Statistic kpi)
{
KPI = kpi;
specificStatisticKPI = DeterminateKpiType(KPI);
RunRequest(specificStatisticKPI)
}
public T DeterminateKpiType<T>(Statistic KPI)
{
if (KPI.GetType() == typeof(LSP))
{
LSP = KPI as LSP;
return LSP;
}
if (KPI.GetType() == typeof(CPU))
{
CPU = KPI as CPU;
return CPU;
}
if (KPI.GetType() == typeof(Memory))
{
Memory = KPI as Memory;
return Memory;
}
}
public void RunRequest(specificStatisticKPI what type ?????)
{
specificStatisticKPI.SomeMethod
}
}
i have a few theories i dont if it would help but i would love to tell you, first specificStatisticKPI what type is it? if its set to be Statistic type i think you need to convert it or it cant contain Memory , LSP or CPU, that is one secondly the RunRequest() method should be able to take three types of classes or the classes can be converted to each other implicitly if these things are handled i believe you code should work .
best of luck
There are a couple of challenges with the approach you're taking (and I suspect that these are causing some of the confusion you're facing) so I will try to outline these and offer solutions that should give you the results you are seeking.
Challenge 1:
You're doing way too much logic in the constructor of your ExecuteRequest class. Constructors should be limited to EXTREMELY simple conditional checks (if any) and should most certainly not perform any operations. Here you would have at least two options:
Refactor your ExecuteRequest class to be a static class with no constructor (I don't see a reason based on your current code to have it be an instantiatable type) and a static method that accepts a Statistic instance as an argument (your RunRequest method for example).
Change the constructor to only initialize the Statistic instance and make the code that consumes ExecuteRequest makes the call to RunRequest.
Of particular note on constructors (taken from MSDN links below):
...The use of public fields is not a recommended programming practice
because it allows any method anywhere in a program unrestricted and
unverified access to an object's inner workings. Data members should
generally be private, and should be accessed only through class
methods and properties.
and
Do minimal work in the constructor. Constructors should not do much
work other than to capture the constructor parameters. The cost of any
other processing should be delayed until required.
Here are some helpful guidelines for constructors and how best to use them:
http://msdn.microsoft.com/en-us/library/ms229060(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/k6sa6h87(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/ms229060(v=vs.100).aspx
Challenge 2:
Using generics and conditional type logic are usually mutually exclusive (where one option is favored over the other) and combining the two is often a Code Smell. When using generics one of the benefits come from the use of 'generic type constraints'. These constraints allow you to know as much as possible about all potential incoming implementations of a base type while allowing new instances to be created without having to modify the code. The idea is essentially one of Liskov Substitution.
For more information on generic type constraints, see: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Here is an excerpt from the MSDN documentation:
By constraining the type parameter, you increase the number of
allowable operations and method calls to those supported by the
constraining type and all types in its inheritance hierarchy.
Therefore, when you design generic classes or methods, if you will be
performing any operation on the generic members beyond simple
assignment or calling any methods not supported by System.Object, you
will have to apply constraints to the type parameter.
Possible Solutions
There are always many ways to solve a programming problem like this, here are two variations that should address the challenges you are facing.
Note: I created these in LinqPad so they are all tested to work (but your actual classes may differ from mine).
Variation 1 (Instantiatable ExecuteRequest with a class-wide generic type constraint):
void Main() {
LSP lspStatistic = new LSP();
Memory memoryStatistic = new Memory();
CPU cpuStatistic = new CPU();
ExecuteRequest<CPU> cpuRequest = new ExecuteRequest<CPU>(cpuStatistic);
ExecuteRequest<LSP> lspRequest = new ExecuteRequest<LSP>(lspStatistic);
ExecuteRequest<Memory> memoryRequest = new ExecuteRequest<Memory>(memoryStatistic);
cpuRequest.RunRequest();
lspRequest.RunRequest();
memoryRequest.RunRequest();
}
public class ExecuteRequest<TStatistic> where TStatistic : Statistic {
private TStatistic _kpi; //Whichever type the class was created as. This enables us to have intellisense support for the specific generic type outside of this class if we need it.
//Hide the default constructor from the outside world (require a statistic)
private ExecuteRequest() : this(null) {
} // end default constructor
public ExecuteRequest(TStatistic kpi) {
_kpi = kpi;
} // end overloaded constructor
public void RunRequest() {
this.KPI.SomeMethod(); //Since we know that KPI will be AT LEAST a Statistic as specified by the generic type constraint, we can access the base class members here without having to figure out which type it is because we don't actually care what type it is, just that it is a Statistic
} // end method RunRequest
public TStatistic KPI {
get {
return _kpi;
} set {
_kpi = value;
}
} // end property KPI
} // end class ExecuteRequest
public abstract class Statistic {
protected Statistic() {
} // end default constructor
public abstract void SomeMethod();
} // end class Statistic
public class LSP : Statistic {
public LSP() : base() {
} // end default constructor
public override void SomeMethod() {
Debug.WriteLine("This is the LSP implementation of SomeMethod.");
} // end method SomeMethod
} // end class LSP
public class CPU : Statistic {
public CPU() : base() {
} // end default constructor
public override void SomeMethod() {
Debug.WriteLine("This is the CPU implementation of SomeMethod.");
} // end method SomeMethod
} // end class CPU
public class Memory : Statistic {
public Memory() : base() {
} // end default constructor
public override void SomeMethod() {
Debug.WriteLine("This is the Memory implementation of SomeMethod.");
} // end method SomeMethod
} // end class Memory
Outputs:
This is the CPU implementation of SomeMethod.
This is the LSP implementation of SomeMethod.
This is the Memory implementation of SomeMethod.
Variation 2 (Static ExecuteRequest with a generic type argument and constraint):
void Main() {
LSP lspStatistic = new LSP();
Memory memoryStatistic = new Memory();
CPU cpuStatistic = new CPU();
ExecuteRequest.RunRequest<LSP>(lspStatistic);
ExecuteRequest.RunRequest<Memory>(memoryStatistic);
ExecuteRequest.RunRequest<CPU>(cpuStatistic);
}
public static class ExecuteRequest {
public static void RunRequest<TStatistic>(TStatistic statInstance) where TStatistic : Statistic {
if(statInstance != null) {
statInstance.SomeMethod();
} // end if
} // end method RunRequest
} // end class ExecuteRequest
Outputs:
This is the LSP implementation of SomeMethod.
This is the Memory implementation of SomeMethod.
This is the CPU implementation of SomeMethod.
As an alternative, since with the static implementation you don't need intellisense, you could omit the generic all-together like so:
void Main() {
LSP lspStatistic = new LSP();
Memory memoryStatistic = new Memory();
CPU cpuStatistic = new CPU();
ExecuteRequest.RunRequest(lspStatistic);
ExecuteRequest.RunRequest(memoryStatistic);
ExecuteRequest.RunRequest(cpuStatistic);
}
public static class ExecuteRequest {
public static void RunRequest(Statistic statInstance){
if(statInstance != null) {
statInstance.SomeMethod();
} // end if
} // end method RunRequest
} // end class ExecuteRequest
Hopefully this gives you some guidance on how to move forward.

Mock set an attribute that doesn't have a set

Hi everyone smarter than me :-) I have another application which requires generation of an abstract class, and due to testing purposes is quite difficult to debug. therefor i created a wrapper and can define my abstract classes in visual Studio now (instead of native application)
However, the native application is expecting public abstract [obj type] values with only a get; method, and if i put in a set;, the application will bomb. Is there any way to set a field using Reflection or Mock to this field, and NOT have the set method?
//simplified class
public abstract class GetEUserAndDetails : [app specific interfaces]
{
public abstract Metastorm.Runtime.Types.Text paramFullNameLike
{
get;
set; //note: If i have this here, it will fail in Metastorm
}
public System.Data.DataSet Read()
{
//do something
}
}
and in Main() it's a c# winform, i have
Mock<Metastorm.Runtime.Models.MySampleProject.GetEUserAndDetails> mockMyBO = new Mock<Metastorm.Runtime.Models.MySampleProject.GetEUserAndDetails>() { CallBase = true };
//using reflection
foreach (PropertyInfo pi in mockMyBO.Object.GetType().GetProperties())
{
//simplified again, another form getting parameters and such
pi.SetValue(mockMyBO.Object, form.myTextParam, null);
}
If I don't have the set method, the pi.SetValue() line will fail, but if i do, it will fail in the native app. (note: i'm using the same test harness to test all sorts of abstract classes that will all implement the Read() method and need to test that it is pulling the correct data back, but the parameters will be different for each class.
Sorry if my code is bad i couldn't get it to format properly, and also please bear with me if i used the wrong terms. I'm not an expert by any means, just enough to be dangerous. I am just living with leaving the set; line for the moment and manually removing it before copy/pasting into the main application, but would like to find another way to do this for when there are many params.
If I understood your scenario correctly, you actually want to test the code in the abstract class, and not mock it.
With that in mind, I think the easiest approach in this case is simply to create a subclass within your test, that will inherit from your base class, and implement whatever is necessary for you to be able to test the base class.
Such as:
public class GetUserAndDetailsImplementation : GetEUserAndDetails
{
private Metastorm.Runtime.Types.Text _paramFullNameLike;
public override Metastorm.Runtime.Types.Text paramFullNameLike
{
get { return _paramFullNameLike; }
}
public void SetParamFullNameLike(Metastorm.Runtime.Types.Text text)
{
_paramFullNameLike = text;
}
}
And you can use that class as entry point for your testing.
Now if you really want to use a mock, have you tried the following?
var mock = new Mock<GetEUserAndDetails> { CallBase = true };
mock.SetupGet(x => x.paramFullNameLike).Returns(<some value>);

Appropriate design/design pattern for this problem?

I previously posted this, but I guess it was too verbose and irrelevant. My question is also like this. One poster in the second link said the answer (of why you can't do the code below) was a problem of design, specifically "bad use of inheritance". So I'd like to check this issue again with the experts at StackOverflow and see if this is really an issue of "bad inheritance" - but more importantly, how to fix the design.
Like the poster, I'm also confused about the Factory method and how I can apply it. It seems the factory method is for multiple concrete classes that have the exact same implementation as the abstract base class and do not add their own properties. But, as you will see below, my concrete classes build upon the abstract base class and add extra properties.
The Base Class We Build Upon:
public abstract class FlatScreenTV
{
public string Size { get; set; }
public string ScreenType { get; set; }
}
Extension Class Examples:
public class PhillipsFlatScreenTV : FlatScreenTV
{
// Specific to Phillips TVs. Controls the backlight intensity of the LCD screen.
public double BackLightIntensity { get; set; }
}
public class SamsungFlatScreenTV : FlatScreenTV
{
// Specific to Samsung TVs. Controls the time until the TV automatically turns off.
public int AutoShutdownTime { get; set; }
}
Let's say there are more extension classes for more brands of flat screen TVs. And then, let's say we stick them all into a generic List:
public static void Main()
{
List<FlatScreenTV> tvList = new List<FlatScreenTV>();
tvList.Add(new PhillipsFlatScreenTV());
tvList.Add(new SamsungFlatScreenTV());
tvList.Add(new SharpFlatScreenTV());
tvList.Add(new VizioFlatScreenTV());
FlatScreenTV tv = tvList[9]; // Randomly get one TV out of our huge list
}
The Problem:
I want to access the specific properties of whatever 'original' brand TV this variable belongs to. I know the brand because if I call tv.GetType(), it returns the correct 'original' type - not FlatScreenTV. But I need to be able to cast tv from FlatScreenTV back to its original type to be able to access the specific properties of each brand of flat-screen TVs.
Question #1: How can I dynamically cast that, properly - without makeshift hacks and huge if-else chains to brute-guess the 'original' type?
After browsing around similar design issues, most answers are: you can't. Some people say to look at the Factory Pattern, and others say to revise the design using interfaces, but I don't know how to use either to solve this problem.
Question #2: So, how should I design these classes so that I can access the original type's specific properties in the context above?
Question #3: Is this really bad inheritance?
Your design violates the "Liskov Substitution Principle". In other words, the code that deals with items from your list of FlatScreenTV shouldn't know or care what derived type is.
Say your code needs to create a custom remote control GUI. It might be enough to simply know the names and types of the properties of each TV to auto-generate the UI. In which case you could do something like this to expose the custom properties from the base class:
public abstract class FlatScreenTV
{
public FlatScreenTV()
{
CustomProperties = new Dictionary<string,object>();
}
public Dictionary<string,object> CustomProperties { get; private set; }
public string Size { get; set; }
public string ScreenType { get; set; }
}
public class PhillipsFlatScreenTV : FlatScreenTV
{
public PhillipsFlatScreenTV()
{
BackLightIntensity = 0;
}
// Specific to Phillips TVs. Controls the backlight intensity of the LCD screen.
public double BackLightIntensity
{
get { return (double)CustomProperties["BackLightIntensity"]; }
set { CustomProperties["BackLightIntensity"] = value; }
}
}
public class SamsungFlatScreenTV : FlatScreenTV
{
public SamsungFlatScreenTV()
{
AutoShutdownTime = 0;
}
// Specific to Samsung TVs. Controls the time until the TV automatically turns off.
public int AutoShutdownTime
{
get { return (int)CustomProperties["AutoShutdownTime"]; }
set { CustomProperties["AutoShutdownTime"] = value; }
}
}
If you really do need to be working directly with the derived types, then you should instead consider moving to a plugin based architecture. For example, you might have a factory method like this:
IRemoteControlGUI GetRemoteControlGUIFor(FlatScreenTV tv)
which would scan your plugins and find the one that knew how to build the UI for the particular type of FlatScreenTV you passed in. This means that for every new FlatScreenTV you add, you also need to create a plugin that knows how to make its remote control GUI.
Factory Pattern would be the best way to go
I can offer a partial answer:
Firstly read up on Liskov's Substitution Principle.
Secondly you are creating objects that inherit from FlatScreenTV, but apparently for no purpose as you want to refer to them by their SubType (SpecificTVType) and not their SuperType (FlatScreenTV) - This is bad use of Inheritance as it is NOT using inheritance lol.
If your code wants to access properties particular to a given type, then you really want this code encapsulated within that type. Otherwise everytime you add a new TV type, all the code that handles the TV list would need to be updated to reflect that.
So you should include a method on FlatScreenTV that does x, and override this in TV's as required.
So basically in your Main method above, instead of thinking I want to be dealing with TVTypeX, you should always refer to the basetype, and let inheritance and method overriding handle the specific behaviour for the subtype you are actually dealing with.
Code eg.
public abstract class FlatScreenTV
{
public virtual void SetOptimumDisplay()
{
//do nothing - base class has no implementation here
}
}
public class PhilipsWD20TV
{
public int BackLightIntensity {get;set;}
public override void SetOptimumDisplay()
{
//Do Something that uses BackLightIntensity
}
}
"the factory method is for multiple concrete classes that have the exact same implementation as the abstract base class [interface] and do not add their own properties."
No, speaking more practical, than theorical, the factory method can provide you with objects of concrete classes, in which the concrete classes, must have some common methods and interfaces, but, also some additional specific attributes.
Sometimes I use a method that creates the same class object every time I called, and I need to call it several times, and sometimes I use a method that create several different class objects, and that maybe be confusing, maybe another question.
And, your further comment about a switch sentence, with many options, when using the factory pattern, you usually provide an identifier for the concrete class / concrete object. This can be a string, an integer, an special type id, or an enumerated type.
You could use an integer / enum ID instead, and use a collection to lookup for the concrete class.
You can still leverage a factory. The point of a factory IMO is to put all the heavy lifting of constructing your various TVs in one place. To say categorically "a factory is for multiple concrete classes that have the exact same implementation as the abstract base class" is forgetting about polymorphism.
There is no law that says you cannot use a factory pattern because the sub classes declare unique properties and methods. But the more you can make use of polymorphism, the more a factory pattern makes sense. Also as a general guideline, IMHO, the more complexity that must go into constructing from the base the better off you are in the long run using a factory because you are "encapsulating change" - that is, constructing concrete classes is likely to change due to differing requirements and inherent construction complexity (a design analysis decision, to be sure) . And that change is in a single class - the factory.
Try this: Define everything in the abstract class and then for a given TV subclass either write concrete-specific code, and for those that don't apply write some standard "I don't do that" code.
Think about all the things your TVs do in generic terms: turn on, turn off, etc. Write a virtual method shell in the base class for all the generic things a TV does - this is a simple example of the template method pattern by the way. Then override these in the concrete classes as appropriate.
There are other things you can do in the base class to make it more fundgeable (that's a technical term meaning "reference subclasses as the base class, but do sub-classy things").
Define delegate methods (very powerful yet under-utilized)
use params[] for dynamic method parameter lists
Make Property delegates
Static methods
Declare Properties and methods "abstract" - forces sub-class implementation, vis-a-vis "virtual"
Hide inherited stuff in the sub class (generally using "new" keyword to communicate that it's on purpose)
If construction parameters are numerous or complex, create a class specifically designed to pass configuration to the factory's build method.
public class TVFactory {
public TV BuildTV(Brands thisKind) {
TV newSet;
switch (thisKind) {
case Brands.Samsung :
Samsung aSamsungTV = new Samsung();
aSamsungTV.BacklightIntensity = double.MinVal;
aSamsungTV.AutoShutdownTime = 45; //oops! I made a magic number. My bad
aSamsungTV.SetAutoShutDownTime = new delegate (newSet.SetASDT);
newSet = aSamsungTV;
break;
. . .
} // switch
}
//more build methods for setting specific parameters
public TV BuildTV (Brands thisKind, string Size) { ... }
// maybe you can pass in a set of properties to exactly control the construction.
// returning a concrete class reference violates the spirit of object oriented programming
public Sony BuildSonyTV (...) {}
public TV BuildTV (Brands thisKind, Dictionary buildParameters) { ... }
}
public class TV {
public string Size { get; set; }
public string ScreenType { get; set; }
public double BackLightIntensity { get; set; }
public int AutoShutdownTime { get; set; }
//define delegates to get/set properties
public delegate int GetAutoShutDownTime ();
public delegate void SetAutoShutDownTime (object obj);
public virtual TurnOn ();
public virtural TurnOff();
// this method implemented by more than one concrete class, so I use that
// as an excuse to declare it in my base.
public virtual SomeSonyPhillipsOnlything () { throw new NotImplementedException("I don't do SonyPhillips stuff"); }
}
public class Samsung : TV {
public Samsung() {
// set the properties, delegates, etc. in the factory
// that way if we ever get new properties we don't open umpteen TV concrete classes
// to add it. We're only altering the TVFactory.
// This demonstrates how a factory isolates code changes for object construction.
}
public override void TurnOn() { // do stuff }
public override void TurnOn() { // do stuff }
public void SamsungUniqueThing () { // do samsung unique stuff }
internal void SetASDT (int i) {
AutoShutDownTime = i;
}
}
// I like enumerations.
// No worries about string gotchas
// we get intellense in Visual Studio
// has a documentation-y quality
enum Brands {
Sony
,Samsung
,Phillips
}

Categories