The first chapter of the study notes of "The design mode of learning in English" original requirements and design
The thing is to start, the company needs to do a set of procedures, ducks, designed as follows:
A duck parent class, multiple derived classes, three override methods.
First demand change
We're going to fly, duck!!!!!.
So we made the following changes:
The parent class added the Fly method, well, all the ducks will fly, the need to achieve!
The problem happened because not all the Ducks would fly
We can overwrite the contents of the parent class's Fly method in the derived class, and the duck will not fly!
Then the problem comes again, if there are a few new kinds of ducks can not fly, is not each have to cover the Fly method Ah????
Maybe, you can use an interface?
Each method is made into an interface,
This is a super-stupid method, if some ducks flying way change, then how many classes to change Ah ...
Now the situation is:
Inheritance is not possible, because the duck's behavior (demand) is constantly changing within the subclass, and the interface cannot be reused.
Fortunately, object-oriented software development has such a principle:
find out where you might need to change in your application, separate them, and don't mix with code that doesn't need to change.
Another way to think about this is to take the changed parts out and wrap them up so that they can be easily changed or expanded in the future without affecting the rest.
So we should extract the duck's behavior.
According to the requirements, we know that the fly and quack behavior of ducks are often changed, so our present design is this:
Design principles:
Programming for interfaces rather than for implementation.
This is the part of the change that defines the interface for fly and quack respectively.
namespace designpatterns.intro.bases{ publicinterface iflybehavior { void Fly ();} } namespace designpatterns.intro.bases{ publicinterface iquackbehavior { void Quack (); }}
Several types of fly and quack are then implemented:
namespacedesignpatterns.intro.derives{ Public classSqueak:iquackbehavior { Public voidQuack () {Console.WriteLine ("Squeak"); } }}namespacedesignpatterns.intro.derives{ Public classNormalquack:iquackbehavior { Public voidQuack () {Console.WriteLine ("Quack"); } }}namespacedesignpatterns.intro.derives{ Public classMutequack:iquackbehavior { Public voidQuack () {Console.WriteLine ("---------"); } }}the act of integrating Ducks
Let's define the Ducks:
namespaceconsoleapp2.bases{ Public Abstract classDuck {Private ReadOnlyIflybehavior _flybehavior; Private ReadOnlyIquackbehavior _quackbehavior; protectedDuck (Iflybehavior Flybehavior =NULL, Iquackbehavior Quackbehavior =NULL) {_flybehavior= Flybehavior??NewFlynoway (); _quackbehavior= Quackbehavior??NewMutequack (); } Public Abstract voidDisplay (); Public voidPerformfly () {_flybehavior.fly (); } Public voidPerformquack () {_quackbehavior.quack (); } Public voidSwim () {Console.WriteLine ("all ducks can swim."); } }}
This is the abstract class of ducks.
Establish the actual ducks:
namespace consoleapp2.derives{ Span style= "COLOR: #0000ff" >public class Mallardduck:duck { public mallardduck (iflybehavior flybehavior =
null , Iquackbehavior quackbehavior =
null ): Span style= "COLOR: #0000ff" >base
(Flybehavior, quackbehavior) {}
public
override
void
Display () {Console.WriteLine (
"
I'm a wild duck ...
"
Test ducks
namespace consoleapp2{ class program { staticvoid Main (string [] args) { varnew mallardduck (newnew Normalquack ()); Duck. Performfly (); Duck. Performquack (); Duck. Display (); Console.ReadLine (); }}}
At this point, the demand has finally been completed!
Our ducks have different effects depending on the incoming fly and the quack implementation class!
The demand has changed and the duck's behavior can be changed at any time.
At this point, we need to dynamically set the behavior, we just need to join the Set method:
Duck The latest code is:
namespaceconsoleapp2.bases{ Public Abstract classDuck { PublicIflybehavior Flybehavior {Private Get;Set; } PublicIquackbehavior Quackbehavior {Private Get;Set; } protectedDuck (Iflybehavior Flybehavior =NULL, Iquackbehavior Quackbehavior =NULL) {Flybehavior= Flybehavior??NewFlynoway (); Quackbehavior= Quackbehavior??NewMutequack (); } Public Abstract voidDisplay (); Public voidPerformfly () {flybehavior.fly (); } Public voidPerformquack () {quackbehavior.quack (); } Public voidSwim () {Console.WriteLine ("all ducks can swim."); } }}
Test results:
namespace consoleapp2{ class program { static
void Main (string [] args) { var duck = n EW Mallardduck (); Duck. Performfly (); Duck. Performquack (); Duck. Display (); Duck. Flybehavior = new flywithwings (); Duck. Quackbehavior = new Squeak (); Duck. Performfly (); Duck. Performquack (); Console.ReadLine (); } }}
Demand complete!!!
The final structure is as follows:
Design principle: Multi-use combination, less inheritance
Design Patterns Learning notes C # code (i)