|
In my continuing, and seemingly endless, quest to understand design patterns and apply them to my code I've encountered the Factory Pattern - and I'm struggling to apply it to my current application, inspite of all the articles and literature on it. Can anyone help my edification?
In my tiered application I have a Business Layer consisting of Business Rules and Entities, and a Data Access Layer which takes care of the Database access.
The current design runs thusly - BLL calls function in DAL, which then queries the database and returns (or doesn't return dependent on the query results) a whole bunch of Entities (such as people, machines, models, sites etc etc) to the BLL.
It's the creation of the entities that's got me puzzled. In the DAL what I do to create them is to loop through a DataReader object and pass the DataReader into the Entity's constructor. This works fine, but I can see the limitations to this approach, not least in that the Entity in question has to know about the DataReader type.
What I'm really struggling with is how to inject the Factory Pattern into this scenario - each class in the DAL is responsible for getting different types of object, and as far as I can see they're kind of unrelated. Does this mean I need a different factory for each? Or can I just make one factory and pass it a value (or whatever) to tell it what type of objects I want created?
Any help appreciated!
|
|
|
|
|
WARNING: I'm new to Factory myself.
Utini wrote: In the DAL what I do to create them is to loop through a DataReader object and pass the DataReader into the Entity's constructor. This works fine, but I can see the limitations to this approach, not least in that the Entity in question has to know about the DataReader type.
My understanding is that the Factory method would only take a simple object, like an identifying string or an int representing a code and use that to decide which class to instantiate. For instance, you pass "RFR" to instantiate a Reversal File Reader and "TDFR" to instantiate a Transaction Detail File Reader. What does your Factory method do with the DataReader? Surely it only uses a single value or two? Just modify the method so it takes only the relevant data, and make them native data types.
Utini wrote: What I'm really struggling with is how to inject the Factory Pattern into this scenario - each class in the DAL is responsible for getting different types of object, and as far as I can see they're kind of unrelated.
Again, my understanding is that a Factory method is to be used when the objects it instantiates are similar in some way - typically/perhaps subclasses of the same superclass. While I think having a Factory method that returns different animals or different file readers is very good design, I wouldn't write a Factory method that returns a Tiger, an Apple, and a TransactionSummaryFileReader.
Again, I must emphasize that I'm new to patterns myself, so take whatever I've said with a pinch large dose of salt. I hope I made some sense, and will gladly welcome others' views on this.
Cheers,
Vikram.
"But nowadays, it means nothing. Features are never frozen, development keeps happening, bugs never get fixed, and documentation is something you might find on wikipedia."
- Marc Clifton on betas. Join the CP group at NationStates. Password: byalmightybob
|
|
|
|
|
Like any tool in software development, patterns can be overused. You always want to keep in mind what problem a pattern seeks to solve and make sure this problem exists (or is likely to exist) in your code. Patterns can be used to make your code more flexible, but they can often make your code more complex.
I know of three Factory patterns: Simple Factory, Factory Method, and Abstract Factory.
Simple Factory and Factory Method encapsulate object creation and allow you to decouple the use of a class from its implementation. This allows you to maintain a level of abstraction in your code. For example, you might have code that uses “automobile” objects. The code that uses the “automobile” doesn’t care if it’s a sports car, sedan, minivan or truck. All it cares about is that it is an “automobile”, which means it can be started, driven, and parked.
The key here is that the objects created by the Simple Factory and Factory Method patterns are related - they either implement the same interface or derive from the same base class.
This doesn’t seem to fit what you have going on in your scenario. You have entities such as person, computer, model, and site. These entities aren’t likely to share a direct base class or implement the same interface.
Abstract Factory allows you group together and encapsulate the creation of families of related objects. So, going back to our automobile example, you might have an abstract factory that deals with the creation of Oil and Gasoline objects. The abstract factory would be defined as an interface with two methods:
Interface CarEssentials
{
Gasoline GetGasoline();
Oil GetOil();
}
You would then implement Concrete Factories to return related Gasoline and Oil objects:
Class SporsCarEssentials : CarEssentials
{
Gasoline GetGasoline() { return UltraUnleaded;}
Oil GetOil() {return HighPerformanceOil;}
}
Class SedanEssentials : CarEssentials
{
Gasoline GetGasoline() { return RegularUnleaded;}
Oil GetOil() {return new StandardOil;}
}
Like the Simple Factory and Factory Method patterns, I don’t see Abstract Factory working for you.
Perhaps the reason you are having difficulty figuring out how to apply a Factory pattern to your code is that the Factory patterns aren’t the right tool for the job.
Then again, I could be completely wrong...
Hope this helps!
Ian
|
|
|
|
|
I'd completely forgotten I'd posted this - until just now!
Thanks both for your answers; Ian, I think what you said is very sound advice! I think I was getting lost in Design Patterns simply because they're there to solve problems that I don't (yet) have.
|
|
|
|
|
Hello,
My bits to byte conversion works for selected items, for unselected items i am trying to make it unselected but the value is not changing.,
this is my piece of code.,
int count = SecurityGroups.Items.Count;
for (int index = 0; index < count; index++)
{
int arrayIndex = Convert.ToInt32(SecurityGroups.Items[index].Value);
if (SecurityGroups.Items[index].Selected)
//convert the bits to bytes
aGroup[arrayIndex / 8] |= (byte)(1 << (arrayIndex % 8));
else
aGroup[arrayIndex] = (byte)(0<< (arrayIndex % 8));
}
for unselected item the conversion part of making those byte to 0 fails. why is it?
i tried making the bit to 0 but that as well does not work
aGroup[arrayIndex] = 0;
With Rgds,
Anil
|
|
|
|
|
Instead of writing your own byte conversion routine, have you tried using the System.BitConverter class?
p.s. you posted duplicate posts. Please delete the other one.
|
|
|
|
|
How do i do that? I cannot use it for this program i guess.
|
|
|
|
|
To convert an int to a byte[], you'd do something like this:
byte[] bytes = BitConverter.GetBytes(theInteger);
Will that work for you?
|
|
|
|
|
No since i do all this based on the selection.
|
|
|
|
|
I got the solution,
I did a bitarray and converted into bytes using this code...
private static byte[] BitArrayToByteArray(BitArray bits)
{
// Who knows, might change
const int BITSPERBYTE = 8;
// Get the size of bytes needed to store all bytes
int bytesize = bits.Length / BITSPERBYTE;
// Any bit left over another byte is necessary
if (bits.Length % BITSPERBYTE > 0)
{
bytesize++;
}
// For the result
byte[] bytes = new byte[bytesize];
// Must init to good value, all zero bit byte has value zero
// Lowest significant bit has a place value of 1, each position to
// to the left doubles the value
byte value = 0;
byte significance = 1;
// Remember where in the input/output arrays
int bytepos = 0;
int bitpos = 0;
while (bitpos < bits.Length)
{
// If the bit is set add its value to the byte
if (true == bits[bitpos])
{
value += significance;
}
bitpos++;
if (0 == bitpos % BITSPERBYTE)
{
// A full byte has been processed, store it
// increase output buffer index and reset work values
bytes[bytepos] = value;
bytepos++;
value = 0;
significance = 1;
}
else
{
// Another bit processed, next has doubled value
significance *= 2;
}
}
return bytes;
}
|
|
|
|
|
AnilUnni wrote: aGroup[arrayIndex] = (byte)(0<< (arrayIndex % 8));
is completely wrong:
1. the array index needs a /8
2. to clear a bit within a byte without affecting the other bits, you need:
either AND with the complement of that bit
or first SET the bit, then EXOR the same bit (to clear it)
|
|
|
|
|
I am new to this shift operator so i am not able follow., can u pls show a sample...
i tried doing this but could not get the result
aGroup[arrayIndex / 8] &= (byte)(~1 << (arrayIndex % 8));
-- modified at 15:09 Monday 23rd April, 2007
|
|
|
|
|
you are almost there, but
in a complex expression you sometimes need parentheses to change the default order
of execution...
If your code does not work, I advice:
- to try something simpler and see if that works, then make it more complex
- look at intermediate values, preferably by logging (= inserting output statements,
e.g. Console.WriteLine(string)).
|
|
|
|
|
Dear Sir,
Could you please help me with this ?
In a PopUp-Window, if I selected a row in a gridview to show another gridview, it will blink always. I used RowDataBound and SelectedIndexChanged-events to select the row in the first gridview.
Why ? Could you show me how to solve the problem ? that it won't blink again everytime I select a row ?
Thank you very very much for your help ..
Juni
|
|
|
|
|
it blinks because it is refreshing the page on slectedindex change.. if you don't want ti to blink, then you have to use either AJAX or load everything from server at the first itme and use javascript to show/hide the required data/gridview.....
-----
|
|
|
|
|
thank you for your answer.. i ve got another question if you don't mind ?
how could i link a hyperlinkfield in a gridview to a popup window ?
thus, what should i do if want to open a popup window if i click a hyperlinkfield in a gridview (i write the programcode in C#)
thank you very much for your help.
JS
|
|
|
|
|
you have to create a javascript function to open a new window, in rowdatabound function find the hyper link and change the onclick function to call the javascript function assing the url to that function. in the javascript function use window.open function to open the window and then return false so that it does not refresh the parent page.
-----
|
|
|
|
|
Does anybody know how to work with Digital Persona finer reader 4000B in C#.Net? and where should i find sample of it.
Thanks in advance.
|Muhamad Waqas Butt|
waqasb4all@yahoo.com
www.sktech.freewebspace.com
|
|
|
|
|
A quick google search reveals SDK material for Digital Persona[^]. Sounds like you need to contact the company first; ask them if they've got a COM or .NET SDK. Either will work in C#, Mr. Butt.
p.s. I love your name, by the way. Puts a smile on my face every time.
|
|
|
|
|
Thanks you Judah Himango. I've visited this web already but i didn't find any thing in it regarding C#.Net. And I also contacted with the company but I thought may be some person try this device, so i posted question on it, anyways, thank you for liking my name.
Take Care & Allah Hafiz (Good Bye)
Butt
|Muhamad Waqas Butt|
waqasb4all@yahoo.com
www.sktech.freewebspace.com
|
|
|
|
|
I read Worker Threads in C# by Alex F, and it seemed to be just what I needed, but I am ignorant enough in C# to have problems and I am desparate enough to repost my question on the main forum for help.
Basically, I have a windows form that takes a bunch of user input and goes off to run a lengthy simulation. I wanted to move the simulation to a separate thread to allow for an abort or pause control on the form, but still be able to post updates back to a box in the form.
I used the nifty Visual C# Express tools to make the form, so the form is partial classes split in two files, by default, the partial class is set to inherit from Form in the designer file, but if I understand how partial classes work it shouldn't matter where that goes. Other than this, I'm pretty sure I have crammed Alex's code into mine correctly. but...
In the class for the process to run on the worker thread, Alex uses
m_form.Invoke(m_form.m_DelegateAddString, new Object[] {s});
I'm not sure what m_form is (or how it relates to MainForm) I know this is some fairly standard example naming convention but I can't figure it out, and I frankly can't figure out anything with the Invoke method available. I've tried just reading about Invoke, but it just left me more confused.
I tried to get the thing to compile just leaving the meat of the long process out, but I get an No overload error with this line
longProcess = new LongProcess(m_EventStopThread, m_EventThreadStopped, this);
I assume because I am missing those parts in the LongProcess Run method.
I'm hoping that someone reading this is familiar with this article (but wouldn't have seen my plea there), and can help.
Unfortunately, I have to present this little project tomorrow with or without the thread , and the thread would be so much more professional...
Thanks in advance,
Ashley
|
|
|
|
|
Ashley,
I recommend you look at the BackgroundWorker[^] component found in .NET v2 and higher. It abstracts away all the invoking stuff for you, thus you don't have to worry about putting things on the right thread; the BackgroundWorker will do it for you. It will raise a DoWork event which will be fired on the background thread. When that's finished, it will raise a RunWorkerCompleted event fired on the UI thread. The article above discusses this in detail.
|
|
|
|
|
I've had a look at the demo app by Alex in his guid to worker threads,
here's what I can see and hopefully it will cast some light on what is wrong.
First m_form is defined within the file LongProcess.cs as
<br />
MainForm m_form;<br />
It is set when the function
<br />
longProcess = new LongProcess(m_EventStopThread, m_EventThreadStopped, this);<br />
is called from MainForm.cs - here 'this' is the MainForm in question. He just stores that instance in 'm_form', that way he can then 'Invoke" things on the MainForm thread later within the Run method in longprocess.cs.
As for why
<br />
longProcess = new LongProcess(m_EventStopThread, m_EventThreadStopped, this);<br />
is causing a compiler problem on your code - my belief would be that you have altered the code somehow so that it no longer acceps THREE parameters, or maybe you have changed the name of your form to be Form1 (which would be the default), if that is the case you need to change the parameter of the Form expected in longprocess.cs in the LongProcess method to be Form1 and not MainForm as in Alex's code.
Hope this helps get you started and good luck with the presentation....
Mark.
|
|
|
|
|
Thanks so much for taking the time to help!!!
Between my post and yours I had finally thought to download the demo (I actually hadn't realized there was a download with this article) and found the problems. I was actually missing all the Members and the LongProcess function from my LongProcess class (so my overload message was because of using a default constructor). Everything is working great now. Back on the article thread I've added an update as well.
As a general note to you super members reading this post:
First, Thank you for all your wonderful articles (saves me hours!!!)
However, I am not a downloader by nature. I think if the two missing elements had been in the sample code, even a beginner/non-downloader could get this going without help. When possible, keep the code samples pretty free standing.
Thanks again,
Ashley
|
|
|
|
|
Hi!
I want to open a user specified URL from C# code, i am using C# 2005. Can any body tell me how will i do it?
Thanks,
Regards,
Affan Ahmad Toor
|
|
|
|
|