Thursday, March 3, 2011

Application of Command Mode

 Command mode of application practice
Filed under: Design & Pattern m bruce zhang @ 1:27 pm
one, needs analysis
in our development of a project, so you need to develop a mounting system for easy deployment of specific environment, production systems. requires the installation of the interface shown in Figure 19-1:
Figure 19-1 System Interface
installed according to the different installation steps, the installation logic to perform the corresponding difference, however, customer requirements is able to provide The whole installation is divided into seven steps:
(1) detect and initialize the local computer to install the system;
(2) choose to install the archive;
(3) install the required replication temporary files;
(4) the selected installation directory;
(5) ready to install;
(6) to perform the installation;
(7) installation is successful, exit.
through the installation steps every step of the installation interface is different, and these interfaces by a specific User Control embodied, for example, in the message User Control, buttons, progress bars, etc..
Second, bad design
Since we each A definition of the different installation steps UserControl object, then run the installation every time, only need to use Pannel control method can add child controls, such as defining the following method:
private void AddBodyUC (UserControl uc)
{
panBody.Controls.Clear ();
panBody.Controls.Add (uc);
panBody.Refresh ();
}
directly in the main form and then we define a number of installation method, and classified according to the direction of installation, for example:
private void PreviousStep1 ()
{}
private void NextStep1 ()
{}
We then define a counter, with Record the number of steps in the installation:
private int step = 1;
the same time, the definition of an enumerated type to specify the direction of installation is the public enum OpDirection {Previous = 0, Next}
easier to call in the implementation of the method based on the installation, again the definition of a series of installation methods, and receive OpDirection object to determine its value based on the implementation of the method:
private void Step1 (OpDirection direction)
{
switch (direction)
{
case OpDirection.Previous:
PreviousStep1 ();
break;
case OpDirection . Next:
NextStep1 ();
break;
}
}
Now, we can directly call the Button's Click event-related methods, for example:
private void btnNext_Click (object sender, System.EventArgs e)
{
switch (step)
{
case 1:
Step1 (OpDirection.Next);
break;
case 2:
Step2 (OpDirection.Next);
break;
case 3:
Step3 (OpDirection.Next);
break;
case 4:
Step4 ( OpDirection.Next);
break;
case 5:
Step5 (OpDirection.Next);
break;
case 6:
Step6 (OpDirection.Next);
break;
case 7:
Step7 (OpDirection.Next);
break;
}
}
can not say that this design is not simple, however, is nothing less bad is not a. In fact, this design really is the legacy of process-oriented design, and completely lost the essence of object-oriented design. rough list about, at least the following shortcomings:
(1) level of confusion, unclear responsibilities, many realize the code is concentrated in a main form class, resulting in too large a class;
(2) the logic is simple, but the code is extremely complicated, and not conducive to code reuse;
(3) is extremely rigid, In particular, against the possible expansion;
(4) thought disorder, structural fuzzy, is not conducive to the code of reading, thus affecting other people may have to modify the code.
short, such a design are like a poor craftsman beat out a semi-random, not to mention not only the beauty of design, not even the most basic design elements are not available. barely say it enough.
So, how design can overcome these shortcomings? In fact From the above design, we can find some clues to improve the design. The most important design principle or object segregation of duties. For example, we think about the installation methods that are the responsibility of the main form object? The answer is obviously no. Since these methods do not belong to the main form object functions, why do we have to define it in the main form class?
So, what are those methods which an object? is defined by each installation steps The UserControl object? seems to be, but not really. a UserControl object, its role should be? Although the definition of the installation steps for each class, but it also is the installation of the main responsibilities of the relevant interface logic, such as related information interface shows the progress of the progress bar shows, but also to respond Button Click event possible implementation methods. and perform the installation, strictly speaking, it has nothing to do with these objects.
can not find the installation method since the object belongs, Why do not specifically define its associated objects? ideas here, and have a clear insight into the joy of the.
Third, the introduction of Command mode
If a typical object should include the properties and behavior, it only contains behavior of the object, without a doubt the best-defined type is interface. in the design of the previous section, define a series of installation method, although the different steps to implement the logic is not the same, but because the same method signature So can a unified interface, such as ISetupCommand:
public interface ISetupCommand
{
void ExecuteSetup ();
}
several installation steps since it is has the Setup () method, natural to define the relevant class, and make it implement the interface:
public class Step1SetupCommand: ISetupCommand
{
public void ExecuteSetup ()
{
/ / implementation omitted;
}
}
a result, the modified design of the class diagram shown in Figure 19-2:
Figure 19-2 ISetupCommand types of class diagrams
Readers should be familiar with design patterns can be seen out, shown above is a standard Command pattern implementation. Indeed, we will install method as a user's request, or a command. As the order is changing in terms of the logic of the system, so the abstract of the order logic, and other calls to the coupling between the loose, is the best solution to solve such problems.
Note: If you compare the class of graph structure, we will find Command Mode, Strategy pattern and State pattern is exactly the same The. The fact is the case, because of their design ideas are easy to change parts of the abstract, or interfaces, or abstract class. The only difference is that the abstract behavior of a different role, which is from their name can be seen. In this case, the installation method more akin to the user's request or order, so called Command mode is more appropriate.
into Command mode indeed make our program structure is more reasonable, however, we using design patterns, not to be applied mechanically, but should follow the basic principles of its design. to this example, but in reality we do not need to define a class such as Step1SetupCommand to achieve ISetupCommand interface. We only need to modify the original installation steps defined for each UserControl class, so that it can achieve ISetupCommand interfaces.
That being said, the installation behavior is still a UserControl's responsibilities? Is this not contradictory with the preceding analysis? is not the case, the difference between the two has utterly. If you just simply put the installation method in the UserControl object, then the responsibility is with the specific binding UserControl Leixing phase, such Step1BodyUC class objects, their relationship is a strong dependence. As UserControl class type. Net Framework has been defined, although various specific UserControl object has a common base class UserControl, however, a common installation method has not been abstracted, it means that the installation of each UserControl object is fragmented, so the following code is wrong of:
UserControl uc = new Step1BodyUC ();
uc.ExecuteSetup ();
be displayed unless the object is converted to Step1BodyUC uc type, but this deal is completely cut out the object-oriented thinking polymorphism.
UserControl object if all are to achieve the ISetupCommand interface, the situation is completely different:
public class Step1BodyUC: UserControl, ISetupCommand
{
/ / implementation omitted;
}
following code is reasonable:
ISetupCommand uc = new Step1BodyUC ();
uc.ExecuteSetup ();
modified design class diagram should be shown in Figure 19-3:
Figure 19-3 revised design class diagram
compared to the original design, we just added a new ISetupCommand interface, while the original class in the main window, the installation method, transferred to each UserControl object, as ISetupCommand interface method implementation.
Fourth, to further improve the program structure
Although the introduction of Command mode has been greatly improved, however, all ISetupCommand existing object and not well be called the main form object. and btnPrevious for btnNext Click the button event behavior to achieve installation, the installation steps must be executed sequentially, while today's design, and does not reflect the relationship between such an order. The only solution is to turn these objects into a ISetupCommand collection of objects, and to provide Next () and Previous () method returns the correct object:
public class SetupUCChain
{
private List m_list;
private int m_step;
private static SetupUCChain m_chain;
private SetupUCChain ()
{
m_list = new List ();
m_step = 0;
Init ();
}
public static SetupUCChain CreateSetupUCChain ()
{
if (m_chain == null)
{
return new SetupUCChain ();
}
else
{
return m_chain;
} < br>}
private void Init ()
{
m_list.Add (new Step1BodyUC ());< br> m_list.Add (new Step2BodyUC ());< br> m_list.Add (new Step3BodyUC ());< br> m_list.Add (new Step4BodyUC ());< br> m_list.Add (new Step5BodyUC ());< br> m_list.Add (new Step6BodyUC ());< br> m_list.Add ( new Step7BodyUC ());< br>}
public ISetupCommand Next ()
{
+ + m_step;
if (m_step {
return ( ISetupCommand) m_list [m_step];
}
else
{
throw new IndexOutOfRangeException (()
{
- m_step;
if (m_step> = 0)
{
return (ISetupCommand) m_list [m_step];
}
else
{
throw new IndexOutOfRangeException (the Singleton pattern.
Finally, due to their installation methods, you need to add the UserControl itself to the main form Pannel control's children, we also need to modify ISetupCommand the interface method, the control object from the parameters passed Pannel:
public interface ISetupCommand
{
void ExecuteSetup (Pannel pannel);
}
UserControl object that in all, it is necessary to achieve the original installation method to add the following code:
panel.Controls.Add (this);
Now, btnPrevious and btnNext button Click event, the logic is very simple:
public class SetupMainForm: System.Windows.Forms.Form
{< br> private System.Windows.Forms.Panel panBody;
private SetupUCChain m_chain = SetupUCChain.CreateSetupUCChain ();
/ / intermediate code slightly;
private void btnNext_Click (object sender, System.EventArgs e) < br> {
try
{
m_chain.Next (). ExecuteSetup (panBody);
}
catch (IndexOutOfRangeException ex)
{
MessageBox.Show (ex. Message);
}
}
private void btnPrevious_Click (object sender, System.EventArgs e)
{
try
{
m_chain.Previous (). ExecuteSetup (panBody );
}
catch (IndexOutOfRangeException ex)
{
MessageBox.Show (ex.Message);
}
}
}
through the introduction of design patterns, the use of the principle of separation of duties, we will strip out the logic related to the installation main form class definition, making the whole structure is clear concise, accountability, and because of possible changes in the package, but also have the scalability, the formation of loose coupling between the structures. so improve the design process that will consume the whole development time of our project, but the effort was not wasted, the improved structure is robust, logical clear, elegant design is also .

No comments:

Post a Comment