赞
踩
此篇为实现篇下,如果对策略者模式不熟,可以看知识点篇上。
实现要求:鸭子共有三种行为,游泳行为(所有鸭子都会),飞行行为(能飞/不能飞/具有火箭动力的飞行),叫声行为(嘎嘎叫/吱吱叫/什么都不会叫),不同具体鸭子(绿头鸭/模型鸭/…)飞行行为和叫声行为可能不一样。
区别:
修饰符不同:接口使用interface修饰,继承使用extends修饰。
多继承方式不同:接口支持多继承,继承只支持单继承。
定义方式不同:接口只能定义全局常量和抽象方法,继承可以定义属性、方法、变量、常量等。
作用不同:接口是一种约束,类实现接口就一定要实现它所有的方法;继承是一种扩展,继承了类,它的私有成员以外的成员变量和成员方法子类都将拥有。
public interface FlyBehavior {
public void fly();
}
public interface QuackBehavior {
public void quack();
}
package com.jiangxue.strategy; public abstract class Duck { //组合(委托):策略类作为抽象基类的成员变量 QuackBehavior quackBehavior; FlyBehavior flyBehavior; //定义抽象方法:子类必须要实现 public abstract void display(); //调用类成员的方法 public void performQuack(){ quackBehavior.quack();; } public void performFly(){ flyBehavior.fly(); } //所有子类都有的共有行为 public void swim(){ System.out.println("All ducks float, even decoys"); } //setter方法设置鸭子行为(运行时改变行为) public void setFlyBehavior(FlyBehavior fb){ flyBehavior = fb; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } }
public class FlyWithWings implements FlyBehavior{ @Override public void fly(){ System.out.println("I'm flying"); } } public class FlyNoWay implements FlyBehavior{ @Override public void fly() { System.out.println("I can't fly"); } } public class FlyRocketPowered implements FlyBehavior{ @Override public void fly() { System.out.println("I'm fly with rocket!"); } }
public class Quack implements QuackBehavior{ @Override public void quack() { System.out.println("Quack"); } } public class MuteQuack implements QuackBehavior{ @Override public void quack() { System.out.println("<<Silence>>"); } } public class Squeak implements QuackBehavior{ @Override public void quack() { System.out.println("Squack"); } }
public class MallardDuck extends Duck{
//重新构造函数
public MallardDuck(){
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public void display(){
System.out.println("I'm a real Mallard duck");
}
}
public class ModelDuck extends Duck{
public ModelDuck(){
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("I'm a model duck");
}
}
public class Test { public static void main(String[] args) { //示例1 Duck mallardDuck = new MallardDuck(); mallardDuck.performQuack(); mallardDuck.performFly(); //示例2 Duck model = new ModelDuck(); model.performFly(); //改变飞行行为 model.setFlyBehavior(new FlyRocketPowered()); model.performFly(); ; } }
class QuackBehavior{
public:
//纯虚函数只有函数的名字而不具备函数的功能,不能被调用,要求任何派生类都要定义自己的实现方法
//有纯虚函数的类是抽象类,不能生成对象,只能派生。
virtual void quack() const = 0;
//virtual析构函数好处:当父类指针指向子类对象时,执行释放操作,子类对象也会被释放掉
virtual ~QuackBehavior() =default;
};
class FlyBehavior{
public:
virtual void fly() const = 0;
virtual ~FlyBehavior() = default;
};
#include <memory> #include "FlyBehavior.h" #include "QuackBehavior.h" #include <iostream> class Duck { protected: //智能指针unique_ptr:独占对象,不允许复制;动态管理分配对象的生命周期 std::unique_ptr<FlyBehavior> _flyBehavior; std::unique_ptr<QuackBehavior> _quackBehavior; public: //explicit表示该构造函数只能显式调用,禁止隐式转换。 /* * 移动语义:不复制对象,而只是让新的对象名指向原对象名所指对象,并且将原对象所指的置空。 * 完美转发:可以撰写接受任意参数的函数模版,并将其转发到其他函数,目标函数会接受与其转发函数所接受的完全相同的参数。 * &&(右值引用):结合了移动语义和完美转发;可以绑定到临时对象。 * std::move(把实参强制转换为右值):无条件地右值类型的强制类型转换; * std::forward:仅对绑定到右值的引用实施向右值类型的强制转换。 * 针对右值引用实施std::move,万能引用实施std::forward */ explicit Duck(std::unique_ptr<FlyBehavior> &&flyBehavior ={}, std::unique_ptr<QuackBehavior> &&quackBehavior={}) :_flyBehavior(std::move(flyBehavior)) ,_quackBehavior(std::move(quackBehavior)){ } //上下文允许在运行时替换策略对象。 void setFlyBehavior(std::unique_ptr<FlyBehavior>&&flyBehavior){ _flyBehavior = std::move(flyBehavior); } void setQuackBehavior(std::unique_ptr<QuackBehavior>&&quackBehavior){ _quackBehavior = std::move(quackBehavior); } //执行飞 void performFly() const{ _flyBehavior->fly(); } //执行叫 void performQuack() const{ _quackBehavior->quack(); } void swim() const{ std::cout<<"All ducks float, even decoys"<<std::endl; } virtual void display() const = 0; };
#include <iostream> #include "FlyBehavior.h" //公有继承:基类的公有成员和保护成员的访问属性在派生类中不变 class FlyWithWings: public FlyBehavior{ public: void fly() const override{ std::cout<<"I'm flying"<<std::endl; } }; class FlyNoWay: public FlyBehavior{ public: void fly() const override{ std::cout<<"I can't fly"<<std::endl; } }; class FlyRocketPowered : public FlyBehavior{ public: void fly() const override{ std::cout<<"I'm fly with rocket!"<<std::endl; } };
#include "QuackBehavior.h" #include <iostream> class Quack: public QuackBehavior{ void quack() const override{ std::cout<<"quack"<<std::endl; } }; class MuteQuack : public QuackBehavior{ public: void quack() const override{ std::cout<<"<<Silence>>"<<std::endl; } }; class Squeak: public QuackBehavior{ void quack() const override{ std::cout<<"Squack"<<std::endl; } };
#include "Duck.h" #include "Quack.h" #include "FlyWithWings.h" #include <iostream> class MallardDuck : public Duck{ public: //子类继承父类的构造 //不能直接从初始化列表初始化基类成员,应该使用父类的构造函数 explicit MallardDuck(std::unique_ptr<FlyWithWings>&& flyWithWings ={}, std::unique_ptr<Quack>&& quack={}) : Duck(std::move(flyWithWings), std::move(quack)){ } //虚函数方法重写 void display() const override{ std::cout<<"I'm a real Mallard duck"<<std::endl; } };
#include "Duck.h" #include "FlyNoWay.h" #include "Quack.h" class ModelDuck :public Duck{ public: explicit ModelDuck(std::unique_ptr<FlyNoWay>&& flyNoWay, std::unique_ptr<Quack>&& quack) : Duck(std::move(flyNoWay), std::move(quack)){ } void display() const override{ std::cout<<"I'm a model duck"<<std::endl; } };
#include "MallardDuck.h" #include "ModelDuck.h" #include "FlyRocketPowered.h" void testCode() { //make_unique函数:动态分配指定类型的内存,并返回一个指向分配内存的唯一指针 MallardDuck mallardDuck(std::make_unique<FlyWithWings>(), std::make_unique<Quack>()); mallardDuck.performQuack(); mallardDuck.performFly(); ModelDuck modelDuck(std::make_unique<FlyNoWay>(), std::make_unique<Quack>()); modelDuck.performFly(); modelDuck.setFlyBehavior(std::make_unique<FlyRocketPowered>()); modelDuck.performFly(); } int main() { testCode(); return 0; }
@abstractmethod
):继承的子类必须实现的方法。@property,@flyBehavior.setter
):调用时不需要加(),为的是提供更加友好访问类数据的方式。def __init__
):初始化类成员变量。super().__init__
):继承父类的属性。from __future__ import annotations
:允许你在程序中声明变量或函数的类型,并由编译器或其他工具来检查代码的类型是否正确。有助于提高代码的可读性,并且有助于发现类型错误。from abc import ABC, abstractmethod
# 抽象基类
class FlyBehavior(ABC):
# 抽象方法
@abstractmethod
def fly(self):
pass
class QuackBehavior(ABC):
@abstractmethod
def quack(self):
pass
class Duck(ABC): def __init__(self, flyBehavior: FlyBehavior, quackBehavior: QuackBehavior) -> None: self._flyBehavior = flyBehavior self._quackBehavior = quackBehavior @abstractmethod def perform(self) -> None: pass def performFly(self) -> None: return self._flyBehavior.fly() def performQuack(self) -> None: return self._quackBehavior.quack() @property def flyBehavior(self) -> FlyBehavior: return self._flyBehavior @property def quackBehavior(self) -> QuackBehavior: return self._quackBehavior @flyBehavior.setter def flyBehavior(self, fly: FlyBehavior) -> None: self._flyBehavior = fly @quackBehavior.setter def quackBehavior(self, quack: QuackBehavior) -> None: self._quackBehavior = quack def swim(self) -> None: print("All ducks float, even decoys")
class FlyWithWings(FlyBehavior):
def fly(self) -> None:
print("I'm flying")
class FlyNoWay(FlyBehavior):
def fly(self) -> None:
print("I can't fly")
class FlyRocketPowered(FlyBehavior):
def fly(self) -> None:
print("I'm fly with rocket!")
class Quack(QuackBehavior):
def quack(self) -> None:
print("Quack")
class Square(QuackBehavior):
def quack(self) -> None:
print("Squack")
class MuteQuack(QuackBehavior):
def quack(self) -> None:
print("<<Silence>>")
class ModelDuck(Duck):
def __init__(self, flyBehavior: FlyNoWay, quackBehavior: Quack) -> None:
super().__init__(flyBehavior, quackBehavior)
# 下面的初始化方法,并不能继承父类的属性
# _flyBehavior = flyBehavior
# _quackBehavior = quackBehavior
def perform(self) -> None:
print("I'm a model duck")
class MallardDuck(Duck):
def __int__(self, flyBehavior: FlyWithWings, quackBehavior: Quack) -> None:
super().__init__(flyBehavior, quackBehavior)
def perform(self) -> None:
print("I'm a real Mallard duck")
# import sys , os # base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # sys.path.append(base_dir) # 没有把当前项目加入到PYTHONPATH环境变量 from Strategy.duck import * if __name__ == "__main__": mallardDuck = MallardDuck(FlyWithWings(), Quack()) mallardDuck.performQuack() mallardDuck.performFly() modelDuck = ModelDuck(FlyNoWay(), Quack()) modelDuck.performFly() modelDuck.flyBehavior = FlyRocketPowered() modelDuck.performFly()
完整的实现代码,见Gitee仓库。如果对您有用的话,欢迎留下star,谢谢。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。