可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In Strategy Design Pattern, what we do is
- Create a common interface.
- Implement a set of classes using that interface with overridden method(s).
- Let the run time to choose the actual class for an object which has the same type with that common interface and call the overridden method(s) which will resolve correctly according to the class.
My question is, Isn't it the basic example of polymorphism and method overriding we learn?
other than the possibility of using an abstract class too, replacing the common interface.
回答1:
What you describe is a way to implement the strategy pattern. You also describe how to implement a whole lot of different designs, since there are many, many reasons why we might want to create a common interface, make different implementations, and select one at runtime for different situations.
There are also other ways to implement the strategy pattern.
But, you know, a design is not code. A design is a mental model of how the software works -- a human thing, not bits. A design pattern is a common way of composing solutions to common sorts of problems. Again it happens in your head and not in bits.
The strategy pattern in particular is about making objects with interchangeable algorithms, any of which could be used for a particular purpose.
So, yes, you define an interface... but it's not the interface to a data object -- it doesn't have getters and setters and state mutators, etc. The interface defines how the object interacts with the algorithm that is used for a particular purpose. A chess game might use a "Player" strategy, for example, with a method called "SelectNextMove".
And, yes you make implementations of that interface, but the implementations aren't "things" that become "parts" of the containing object, they are different algorithms that could be used to perform whatever function the object requires. A chess game could support many different strategies that could be used to select the next move for the computer player.
So when you're thinking about the design of a chess game, for example, in your head, you will probably find it useful to think about strategy for choosing the next move separately from the objects that model the board and ensure that the selected move is recorded, communicated, and rendered properly. The strategy for choosing the next move is independent of these things.
If you're a good software designer, you will code it independently too, so that the separation of concerns in code will mirror the separation of concerns in your head, make it easy for people maintaining the code to think about it in the most useful way, and allow new strategies for choosing the next move to be swapped in and out whenever you want.
回答2:
Strategy implementation can be even simpler in dynamic languages such Javascript. Whenever you pass a callback arround, your are probably extending a Strategy implementation.
Example: sorting arrays
Javascript's native arrays have a method called sort
that will return a brand new sorted array. It can have one parameter, the comparisonFunction
, a callback that will compare 2 items in the array and return:
1
if the first element is to be considered higher than the second.
0
if it is to be considered equal
-1
if it is to be considered lower then
So, you can use whatever strategy you want to sort the array:
[5, 2, 4, 1, 3].sort(); // default: sort in the natural order
[5, 2, 4, 1, 3].sort(function reverse(first, second){
if (first > second) return -1;
if (first == second) return 0;
if (first < second) return 1;
});
[5, 2, 4, 1, 3].sort(function random(first, second){
return Math.floor(Math.random() * 3) - 1;
});
When you are creating your on libraries and expect a callback that will do some work on your data, you are probably implementing the Strategy pattern.
回答3:
Polymorphism is one of the three key pillars of Object Oriented Programming:
Polymorphism
In programming languages and type theory, polymorphism [...] is the provision of a single interface to entities of different types.
Abstraction
[A]bstraction is a technique for managing complexity of computer systems. It works by establishing a level of complexity on which a person interacts with the system, suppressing the more complex details below the current level. The programmer works with an idealized interface (usually well defined) and can add additional levels of functionality that would otherwise be too complex to handle.
Inheritance
In object-oriented programming, inheritance is when an object or class is based on another object (prototypal inheritance) or class (class-based inheritance), using the same implementation (inheriting from an object or class) specifying implementation to maintain the same behavior (realizing an interface; inheriting behavior). It is a mechanism for code reuse and to allow independent extensions of the original software via public classes and interfaces.
Being such a key pillar of OOP, to say there the same thing is akin to saying racing is the same thing as driving (driving being the "core underlying thing" that you're doing). This is also like saying the Facade Pattern is simply Abstraction.
Much like racing is driving fast and competitively, the Strategy Pattern is Polymorphism used at runtime to select an algorithm's behavior. It is an application and implementation of Polymorphism, absolutely, but it's really a specific application and implementation of Polymorphism.
回答4:
Polymorphism: there is an interface or base class where concrete implementations can be exchanged.
Strategy Pattern: A part of a logic is put into a separate class accessed by an interface in order to exchange it. It's therefore using polymorphism in a specific way.
Many OO patterns are using polymorphism. And most of them are kind of basic. Let's take the composite pattern, which I always refer to as the one which shows the power of polymorphism best.
回答5:
Strategy_pattern uses run-time polymorphism to make algorithms interchangeable within that family.
Replacing one algorithm with-in family of multiple algorithms is one part of Strategy pattern. Strategy pattern can use Context also.
You can achieve replacement of algorithm at run time without using interface/run-time polymorphism.
Call a method in Context by passing a condition. Have switch case statements calling different methods based on individual case. This approach is not as clean as run-time polymorphism but still you can achieve it.
Strategy UML:
Related posts:
Confused about strategy design pattern
回答6:
Strategy can be used as an example of Polymorphism in some manners. But it's not a good start for OOP newbies as it's more complex than other patterns.
Yes you can replace interface with abstract class and even normal class. It doesn't matter. "Abstraction" in OOP is not all classes must be derivative of an abstract class or interface.
回答7:
I'd like to add that when using polymorphism you must typically destroy the object and replace it with a new instance. It could be expensive to constantly create/destroy the new instance. The strategy pattern is one way you can implement lazy loading/storing previously created instances for later.
Here is an example in Swift.
protocol Strategy {
}
class CheapStrategy: Strategy {
// cheap to create this
}
class ExpensiveStrategy: Strategy {
// expensive to create this
}
// Polymorphism
// Alternating between different strategies.
// The previous value of s is always created and destroyed.
var s: Strategy!
s = CheapStrategy()
s = ExpensiveStrategy()
s = CheapStrategy()
s = ExpensiveStrategy()
// Strategy Pattern
class Context {
lazy var cheapStrategy = CheapStrategy()
lazy var expensiveStrategy = ExpensiveStrategy()
var s: Strategy!
}
// Alternate between different strategies using previously allocated.
let c = Context()
c.s = c.cheapStrategy
c.s = c.expensiveStrategy
c.s = c.cheapStrategy
c.s = c.expensiveStrategy