In the last blog we mentioned the Simple factory model, however, there is no shadow of her in the 23 design patterns summarized by GOF, in strict sense, the simple factory model is not a design pattern, because she does not conform to the open-closed principle of design pattern, that is, the software entity such as class, module and so on should be able to expand, But not modifiable. For design patterns of design principles, will be introduced in the next article posting, here we look at an example:
It is well known that the supermarket cashier system has billing function, then you have to do a can according to the input of the commodity price and quantity, as well as the billing method to calculate the module, how do you do. Billing method is no discount, there are rebate concessions and so on. So let's start with a simple factory model.
Simple Factory implementation
Using System;
Using System.Collections.Generic;
Using System.ComponentModel;
Using System.Data;
Using System.Drawing;
Using System.Linq;
Using System.Text;
Using System.Threading.Tasks;
Using System.Windows.Forms; Namespace store cashier software {public partial class Form1:form {public Form1 () {Initializecomp
Onent ();
Double total = 0.0d; private void textBox1_TextChanged (object sender, EventArgs e) {} private void Label5_click (Obje
CT sender, EventArgs e) {} private void Form1_Load (object sender, EventArgs e) {
CbxType.Items.AddRange (new object[] {"Normal charge", "full 300 back 100", "80 percent"}); Cbxtype.
SelectedIndex = 0; } private void Buttonok_click (object sender, EventArgs e) {cashsuper csuper = cashfactory.cr
Eatecashaccept (CbxType.SelectedItem.ToString ());
Double totalprices = 0d; Totalprices = Csuper.Acceptcash (convert.todouble (txtprice.text) * convert.todouble (Txtnum.text));
Total = Total + totalprices; LBXLIST.ITEMS.ADD ("Price:" + Txtprice.text + "Quantity:" + Txtnum.text + "Billing method:" + Cbxtype.selecteditem + "total:" + Totalprices.tostrin
g ()); Lblresult.text = total.
ToString ();
} private void Button2_Click (object sender, EventArgs e) {txtnum.text = "";
Txtprice.text = "";
LbxList.Items.Clear ();
Lblresult.text = "0.00";
///Cash charge abstract class Cashsuper {public abstract double acceptcash (double);
//Normal charge subclass class Cashnormal:cashsuper {public override double Acceptcash (double) {
return money;
}//Discounted charges subclass class Cashrebate:cashsuper {private double moneyrebate = 1d; Public cashrebate (String moneyrebate) {this.moneyrebate = double. PArse (moneyrebate);
Override double Acceptcash (double) {return money * moneyrebate;
}//Rebate charge subclass class Cashreturn:cashsuper {private double moneycondition = 0.0d;
Private double moneyreturn = 0.0d; Public Cashreturn (String moneycondition, String moneyreturn) {this.moneycondition = double.
Parse (moneycondition); This.moneyreturn = Double.
Parse (Moneyreturn);
Override double Acceptcash (double) {double = money;
if (Money >= moneycondition) result = Money-math.floor (money/moneycondition) * Moneyreturn;
return result;
///Cash charge factory class Cashfactory {public static cashsuper createcashaccept (String type) {
Cashsuper cs = null;
Switch (type) {case "normal charge": CS = new Cashnormal ();
Break
Case "Full 300 return": Cashreturn CR1 = new Cashreturn ("300", "100");
CS = CR1;
Break
Case "Dozen 80 percent": cashrebate Cr2 = new Cashrebate ("0.8");
CS = Cr2;
Break
} return CS;
}
}
}
We see that this scheme is characterized by the accounting method of the instantiation of the factory, so that when you need to add a new billing method, just put the conditions in the factory, the end of the design of a corresponding class can be. But it also undermines the open-closing principle, and every expansion has to be a tough one, which is bad. How to deal with the constant changes in the algorithm. Here's another way to try:
Policy Pattern implementation
Using System;
Using System.Collections.Generic;
Using System.ComponentModel;
Using System.Data;
Using System.Drawing;
Using System.Linq;
Using System.Text;
Using System.Threading.Tasks;
Using System.Windows.Forms; Namespace store cashier software {public partial class Form1:form {public Form1 () {Initializecomp
Onent ();
Double total = 0.0d; private void textBox1_TextChanged (object sender, EventArgs e) {} private void Label5_click (Obje
CT sender, EventArgs e) {} private void Form1_Load (object sender, EventArgs e) {
CbxType.Items.AddRange (new object[] {"Normal charge", "full 300 back 100", "80 percent"}); Cbxtype.
SelectedIndex = 0; private void Buttonok_click (object sender, EventArgs e) {//Simple factory-mode client code//CASHS
Uper Csuper = cashfactory.createcashaccept (cbxType.SelectedItem.ToString ());
Double totalprices = 0d; Totalprices = Csuper.acceptcash (convert.todouble (txtprice.text) * convert.todouble (Txtnum.text));
Total = Total + totalprices; LBXLIST.ITEMS.ADD ("Price:" + Txtprice.text + "Quantity:" + Txtnum.text + "Billing method:" + Cbxtype.selecteditem + "total:" + totalprices.tostr
ing ()); Lblresult.text = total.
ToString ();
Client code for the policy mode cashcontext cc = NULL; Switch (cbxType.SelectedItem.ToString ()) {case "normal charge": cc = new Cashconte
XT (New Cashnormal ());
Break
Case "Full 300": CC = new Cashcontext (New Cashreturn ("300", "100"));
Break
Case "hit 80 percent": cc = new Cashcontext (New Cashrebate ("0.8"));
Break
Double totalprices = 0d; Totalprices = cc.
GetResult (convert.todouble (txtprice.text) * convert.todouble (Txtnum.text)); Total = Total + totalprices; LBXLIST.ITEMS.ADD ("Price:" + Txtprice.text + "Quantity:" + Txtnum.text + "Billing method:" + Cbxtype.selecteditem + "total:" + totalprices.tostr
ing ()); Lblresult.text = total.
ToString ();
} private void Button2_Click (object sender, EventArgs e) {txtnum.text = "";
Txtprice.text = "";
LbxList.Items.Clear ();
Lblresult.text = "0.00";
///Cash charge abstract class Cashsuper {public abstract double acceptcash (double);
//Normal charge subclass class Cashnormal:cashsuper {public override double Acceptcash (double) {
return money;
}//Discounted charges subclass class Cashrebate:cashsuper {private double moneyrebate = 1d; Public cashrebate (String moneyrebate) {this.moneyrebate = double.
Parse (moneyrebate); public override double Acceptcash (double mOney) {return money * moneyrebate;
}//Rebate charge subclass class Cashreturn:cashsuper {private double moneycondition = 0.0d;
Private double moneyreturn = 0.0d; Public Cashreturn (String moneycondition, String moneyreturn) {this.moneycondition = double.
Parse (moneycondition); This.moneyreturn = Double.
Parse (Moneyreturn);
Override double Acceptcash (double) {double = money;
if (Money >= moneycondition) result = Money-math.floor (money/moneycondition) * Moneyreturn;
return result;
///Cash Charges factory class//class cashfactory//{//public static Cashsuper createcashaccept (String type)
{//CASHSUPER CS = null;
switch (type)//{//Case "normal charge"://cs = new Cashnormal (); Break
Case "Full 300"://Cashreturn CR1 = new Cashreturn ("300", "100");
CS = CR1;
Break
Case "hit 80 percent"://cashrebate CR2 = new Cashrebate ("0.8");
CS = Cr2;
Break
}//RETURN CS;
}//}//cashcontext classes class Cashcontext {private Cashsuper cs;
Public Cashcontext (Cashsuper csuper) {this.cs = Csuper;
Public double GetResult (double) {return Cs.acceptcash (money);
}
}
}
Compared with two scenarios, we can see that the difference is that the policy model will be the factory class removed, replaced by the Cashcontext class, but will realize which algorithm to the client, so that the responsibility of the client is big, bad, bad ...
What to do. Either mix the simple factory and the policy pattern. Try. For their combination, just the Cashcontext class can be modified, as follows:
The reformed Cashcontext class
Cashcontext
{
Cashsuper cs = null;
Public Cashcontext (String type)
{
switch (type)
{case
"normal charge":
cashnormal cs0 = new Cashnormal (); C9/>cs = Cs0;
break;
Case "Full 300":
cashreturn CR1 = new Cashreturn (",");
cs = CR1;
break;
Case "Dozen 80 percent":
cashrebate Cr2 = new Cashrebate ("0.8");
cs = Cr2;
break;
}
}
Public double GetResult (double)
{return
Cs.acceptcash (money);
}
}
As a result, the client's code is much simpler, the simple factory model needs to let the client and two classes Cashsuper and Cashfactory deal with, and the strategy model and the use of simple factory, the client can only deal with the Cashcontext to complete the corresponding functions, Reduce the coupling. Let's go back and look at the definition of the policy pattern:
Policy pattern: Defines the algorithm family, encapsulates each other, lets them replace each other, this pattern lets the algorithm change, does not affect to use this algorithm the customer.