. The design pattern in net: Combination mode

Source: Internet
Author: User
Tags bool rand tostring
Design mix mode (composite) is a "structured" mode (structural). A structured pattern involves two or more objects, representing activities between objects, related to the structure of the object.
Let's start with a small example of a combination pattern:



In figure: There are two kinds of box:game box and Internet box in the system, the customer needs to know the interface of two classes to be called separately. To simplify the customer's work, the Xbox class was created with the following program code:

Code for Gamebox:

public class Gamebox

{

public void PlayGame ()

{

Console.WriteLine ("Plaly Game");

}

}


Code for Internetbox:

public class Internetbox

{

public void Connecttointernet ()

{

Console.WriteLine ("Connect to the Internet");

}

public void Getmail ()

{

Console.WriteLine ("Check Email");

}

}


Xbox's Code:

public class XBox

{

Private Gamebox Mgamebox=null;

Private Internetbox Minternetbox=null;



Public XBox ()

{

Mgamebox = new Gamebox ();

Minternetbox = new Internetbox ();

}

public void PlayGame ()

{

Mgamebox.playgame ();

}

public void Connecttointernet ()

{

Minternetbox.connecttointernet ();

}

public void Getmail ()

{

Minternetbox.getmail ();

}

}


The Xbox encapsulates the Gamebox and Internetbox methods so that the user's face is greatly simplified and the code invoked is as follows:

public class Cscomposite

{

static void Main (string[] args)

{

Xbox x = new Xbox ();

Console.WriteLine ("playgame!");

X.playgame ();

Console.WriteLine ();



Console.WriteLine ("Internet play game!");

X.connecttointernet ();

X.playgame ();

Console.WriteLine ();



Console.WriteLine ("e-mail!");

X.getmail ();

}

}


As you can see, the user only needs to know the Xbox's interface.

Examples of application of combinatorial patterns

The combination mode applies to situations such as the following: two or more classes have similar forms, or collectively represent a complete concept, and outside users want them to be one, they can "combine" these several classes to become a new class, the user only need to call the new class on it.

Here is an example to illustrate a practical application of the composite pattern. The following Class View:



The employee class is an implementation of the Abstractemployee interface, the Boss class is a subclass of employee, Empnode is inherited from the TreeNode class of the tree view. Let's look at the code first:

Abstractemployee, which is an interface, provides the following methods:

Public interface Abstractemployee {

float getsalary (); Get current Salary

String GetName (); Get Name

BOOL IsLeaf (); True if leaf

void Add (string nm, float salary); Add subordinate

void Add (Abstractemployee emp); Add subordinate

IEnumerator Getsubordinates (); Get Subordinates

Abstractemployee Getchild (); Get Child

float getsalaries (); Get salaries of all

}


The employee class is an implementation of the Abstractemployee interface

public class Employee:abstractemployee {

protected float salary;

protected string name;

protected ArrayList Subordinates;

 

//------

Public Employee (string nm, float salry) {

Subordinates = new ArrayList ();

name = NM;

salary = Salry;

}

 

//------

public float getsalary () {

return salary;

}

 

//------

public string GetName () {

return name;

}

 

//------

public bool IsLeaf () {

Return subordinates. Count = 0;

}

 

//------

Public virtual void Add (string nm, float salary) {

throw new Exception ("No Subordinates in Base employee Class");

}

 

//------

Public virtual void Add (Abstractemployee emp) {

throw new Exception ("No Subordinates in Base employee Class");

}

 

//------

Public IEnumerator Getsubordinates () {

Return subordinates. GetEnumerator ();

}

 

Public virtual Abstractemployee Getchild () {

return null;

}

 

//------

public float getsalaries () {

float sum;

Abstractemployee ESub;

Get the salaries of the boss and subordinates

sum = Getsalary ();

IEnumerator enumsub = Subordinates. GetEnumerator ();

while (Enumsub.movenext ()) {

ESub = (abstractemployee) enumsub.current;

Sum + + esub.getsalaries ();

}

return sum;

}

}


From the employee interface and one of his implementations, it is possible to combine this type of data into a tree structure.

The Boss class is a derivation of the employee class, and he overloads the add and Getchild methods of the Employee class:

public class Boss:employee

{

Public Boss (string name, float salary): base (name,salary) {

}

 

//------

Public Boss (Abstractemployee EMP): Base (Emp.getname (), Emp.getsalary ()) {

}

 

//------

public override void Add (string nm, float salary) {

Abstractemployee emp = new Employee (nm,salary);

Subordinates. ADD (EMP);

}

 

//------

public override void Add (Abstractemployee emp) {

Subordinates. ADD (EMP);

}

 

//------

public override Abstractemployee Getchild () {

BOOL found;

Abstractemployee tEmp = null;

IEnumerator ESub;

 

if (GetName (). Equals (GetName ()))

return this;

else {

Found = false;

ESub = Subordinates. GetEnumerator ();

while (! Found && esub. MoveNext ()) {

TEMP = (abstractemployee) esub. Current;

Found = (Temp.getname (). Equals (name));

if (! found) {

if (! temp.isleaf ()) {

TEMP = Temp.getchild ();

Found = (Temp.getname (). Equals (name));

}

}

}

if (found)

return TEMP;

Else

Return to New Employee ("New Person", 0);

}

}

}


The Getchild method is a recursive call, and if the child is not a leaf, continue to call it down. The above classes express the structure of a tree, representing the level of leadership and employee relationships in the company.

Now let's take a look at what this program needs to achieve, and after the program is run, show the following interface:



There is a tree on the screen, the tree shows the organization of a company's personnel, click on these employees, will appear below the person's salary. Now there are two trees in the program: one is the actual tree on the screen, the other is the virtual tree of employees in the company. The tree node on the screen is the TreeNode type, and the employee's virtual tree node is the Abstractemployee type. We can use the combination mode, create a new "node", combining the characteristics of these two nodes, to simplify the form class needs to deal with, see the following code:

public class Empnode:treenode {

Private Abstractemployee EMP;

 

Public Empnode (Abstractemployee aemp): Base (Aemp.getname ()) {

EMP = aemp;

}

 

//-----

Public Abstractemployee GetEmployee () {

return EMP;

}

}


The Empnode class is a subclass of the TreeNode class that has all the attributes of the TreeNode class, and he also combines the characteristics of the Abstractemployee type. Since then, the work of the caller has been simplified. Here is a snippet of the form class, and I omitted part of the auto-generated code:

public class Form1:System.Windows.Forms.Form {

Private System.Windows.Forms.Label lbsalary;

 

<summary>

Required designer variable.

</summary>

Private System.ComponentModel.Container components = null;

Abstractemployee prez, MARKETVP, salesmgr;

TreeNode RootNode;

Abstractemployee advmgr, EMP, PRODVP, Prodmgr, shipmgr;

Private System.Windows.Forms.TreeView Emptree;

Private Random Rand;

 

private void init () {

Rand = new Random ();

Buildemployeelist ();

Buildtree ();

}

 

//---------------

private void Buildemployeelist () {

Prez = new Boss ("CEO", 200000);

MARKETVP = new Boss ("Marketing VP", 100000);

Prez.add (MARKETVP);

Salesmgr = new Boss ("Sales Mgr", 50000);

Advmgr = new Boss ("Advt Mgr", 50000);

Marketvp.add (salesmgr);

Marketvp.add (advmgr);

PRODVP = new Boss ("Production VP", 100000);

Prez.add (PRODVP);

Advmgr.add ("Secy", 20000);

 

Add salesmen reporting to Sales Manager

for (int i = 1; i<=5; i++) {

Salesmgr.add ("Sales" + i.tostring (), Rand_sal (30000));

}

Prodmgr = new Boss ("Prod Mgr", 40000);

Shipmgr = new Boss ("Ship Mgr", 35000);

Prodvp.add (prodmgr);

Prodvp.add (shipmgr);

 

for (int i = 1; i<=3; i++) {

Shipmgr.add ("Ship" + i.tostring (), Rand_sal (25000));

}

for (int i = 1; i<=4; i++) {

Prodmgr.add ("Manuf" + i.tostring (), Rand_sal (20000));

}

}

 

//-----

private void Buildtree () {

Empnode nod;

nod = new Empnode (prez);

RootNode = nod;

EMPTREE.NODES.ADD (NOD);

AddNodes (nod, Prez);

}

 

//------

private void Getnodesum (Empnode node) {

Abstractemployee EMP;

float sum;

EMP = Node.getemployee ();

sum = Emp.getsalaries ();

Lbsalary.text = Sum. ToString ();

}

 

//------

private void AddNodes (Empnode nod, Abstractemployee EMP) {

Abstractemployee newemp;

Empnode NewNode;

IEnumerator Empenum;

Empenum = Emp.getsubordinates ();

 

while (Empenum.movenext ()) {

Newemp = (abstractemployee) empenum.current;

NewNode = new Empnode (newemp);

Nod. Nodes.Add (NewNode);

AddNodes (NewNode, newemp);

}

}

 

//------

Private float rand_sal (float sal) {

float rnum = rand. Next ();

Rnum = Rnum/int32.maxvalue;

Return rnum * SAL/5 + sal;

}

 

//------

Public Form1 () {

//

Required for Windows Form Designer support

//

InitializeComponent ();

Init ();

//

Todo:add any constructor the code after InitializeComponent call

//

}

 

<summary>

Clean up any being used.

</summary>

protected override void Dispose (bool disposing) {

if (disposing) {

if (components!= null) {

Components. Dispose ();

}

}

Base. Dispose (disposing);

}


<summary>

The main entry point is for the application.

</summary>

[STAThread]

static void Main () {

Application.Run (New Form1 ());

}

 

private void Emptree_afterselect (object sender, TreeViewEventArgs e) {

Empnode node;

node = (empnode) Emptree.selectednode;

Getnodesum (node);

}

}


The Emptree_afterselect method is the tree graph clicks the node event the response method, the user clicks the node to display the corresponding salary in the text column. The combination mode has been introduced, and the following things have nothing to do with the combination mode.

Why use interface?

Why do you want to create an employee's interface in a program? We can create a class Employee, and then derive the boss, as can achieve the above function.

Using interface is to separate the display program on the screen from the background business data program. The display program of the screen only needs to care about what interfaces the employee provides to work, without having to meddle with specific details, such as the calculation rules for wages. This is also possible if you need to unit test the interface class and data classes separately (that is, the program is testable). When testing the screen, you can implement some false employee classes on the employee interface, and the methods and properties are faked for testing so that you can test whether the interface is displayed correctly. In general, if you want to perform unit tests, you should consider the "testability" of the program from the design stage, which is important: separate the interface representation from the business logic.

about how to improve the testability of the program, I will arrange some experience in the future.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.