装饰器模式和策略模式
装饰器模式
定义:在不改变原有对象的基础上,将功能附加到对象上
比如原有一个拍照的功能,在这个功能的基础上,添加美颜和滤镜
//定义原有功能接口
public interface Component {
void operation();
}
//原始功能的实现
public class ConcreteComponent implements Component{
@Override
public void operation() {
System.out.println("拍照");
}
}
//定义装饰器
public abstract class Decorator implements Component{
protected Component component;
public Decorator(Component component){
this.component = component;
}
}
//装饰器附加功能
class ConreteDecorator extends Decorator{
public ConreteDecorator(Component component) {
super(component);
}
@Override
public void operation() {
System.out.println("美颜");
super.component.operation();
}
}
//装饰器附加功能2
class ConreteDecorator1 extends Decorator{
public ConreteDecorator1(Component component) {
super(component);
}
@Override
public void operation() {
System.out.println("滤镜");
super.component.operation();
}
}
测试:
public class Test {
public static void main(String[] args) {
Component component = new ConreteDecorator1(new ConreteDecorator(new ConcreteComponent()));
component.operation();
}
}
应用场景:
扩展一个类的功能或给一个类添加附加职责
优点:
1.不改变原有对象的情况下给一个对象扩展功能
2.使用不同的组合可以实现不同的效果
3.符合开闭原则
策略模式
定义:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式的变 化独立于算法的使用者。
比如说开发一个植物大战僵尸的游戏,定义一些僵尸,每种僵尸的类型、外观、移动、攻击等等有所不同。
比如第一版本 可能只有两种类型僵尸:普通僵尸和旗手僵尸 他们的外观不同、其他的移动和攻击相同
如果用传统代码编写 如下
//定义僵尸的抽象父类
public abstract class AbstractZombie {
//外观不同 定义为抽象方法
public abstract void display();
//其他方式相同 定义为普通方法
public void move(){
System.out.println("一步一步移动");
}
public void attack(){
System.out.println("咬");
}
}
//定义僵尸
public class NormalZombie extends AbstractZombie{
@Override
public void display() {
System.out.println("我是普通僵尸");
}
}
class FlagZombie extends AbstractZombie{
@Override
public void display() {
System.out.println("我是旗手僵尸");
}
}
测试:
public class Test {
public static void main(String[] args) {
AbstractZombie zombie = new NormalZombie();
AbstractZombie zombie1 = new FlagZombie();
zombie.display();
zombie.move();
zombie.attack();
System.out.println("---------------");
zombie1.display();
zombie1.move();
zombie1.attack();
}
}
后续随着业务发展,需要定义其他僵尸,比如定义大头僵尸,移动和以前相同,但是攻击是头撞
class BigHeadZombie extends AbstractZombie{
@Override
public void display() {
System.out.println("我是大头僵尸");
}
@Override
public void attack() {
System.out.println("头撞");
}
}
后续又定义了其他僵尸,攻击还是头撞,但是移动变了
class XxxZombie extends BigHeadZombie{
@Override
public void move() {
System.out.println("跳着舞移动");
}
@Override
public void display() {
System.out.println("我是其他僵尸");
}
}
这样随着业务的发展,继承越来越多,代码越来越复杂,维护管理都变得复杂。
那么使用策略模式进行改进。
首先把稳定的部分抽象出来,像移动、攻击、外观。每种僵尸都有这三种行为
//定义公用行为的策略接口
public interface Moveable {
void move();
}
interface Attackable{
void attack();
}
//移动的具体实现策略
public class StepByStepMove implements Moveable{
@Override
public void move() {
System.out.println("一步一步移动");
}
}
class DancingMove implements Moveable{
@Override
public void move() {
System.out.println("跳着舞移动");
}
}
//攻击策略
public class ComAttack implements Attackable{
@Override
public void attack() {
System.out.println("咬");
}
}
class HitAttack implements Attackable{
@Override
public void attack() {
System.out.println("打");
}
}
//定义僵尸抽象父类
public abstract class Zombie {
protected abstract void display();
protected Moveable moveable;
protected Attackable attackable;
abstract void move();
abstract void attack();
//构造方法 传入不同的策略
public Zombie(Moveable moveable, Attackable attackable) {
this.moveable = moveable;
this.attackable = attackable;
}
//set get方法随时修改策略
public Moveable getMoveable() {
return moveable;
}
public void setMoveable(Moveable moveable) {
this.moveable = moveable;
}
public Attackable getAttackable() {
return attackable;
}
public void setAttackable(Attackable attackable) {
this.attackable = attackable;
}
}
public class NormalZombie extends Zombie{
public NormalZombie(){
super(new StepByStepMove(),new ComAttack());
}
public NormalZombie(Moveable moveable, Attackable attackable) {
super(moveable, attackable);
}
@Override
protected void display() {
System.out.println("我是普通僵尸");
}
@Override
void move() {
super.moveable.move();
}
@Override
void attack() {
super.attackable.attack();
}
}
public class FlagZombie extends Zombie{
public FlagZombie(){
super(new StepByStepMove(),new ComAttack());
}
public FlagZombie(Moveable moveable, Attackable attackable) {
super(moveable, attackable);
}
@Override
protected void display() {
System.out.println("我是旗手僵尸");
}
@Override
void move() {
super.moveable.move();
}
@Override
void attack() {
super.attackable.attack();
}
}
测试:
public class Test {
public static void main(String[] args) {
Zombie zombie = new NormalZombie();
zombie.display();
zombie.move();
zombie.attack();
//当想要修改攻击方式 只需要传入不同的攻击策略即可 不需要要修改代码
zombie.setAttackable(new HitAttack());
zombie.attack();
}
}
当后续僵尸有不同的移动、攻击 只需要传入不同的移动、攻击策略,不需要修改实体类的代码,所有的僵尸类型都只继承了相同的抽象父类。维护简单
应用场景
1.当你有很多类似的类,但它们执行某些行为的方式不同时,请使用此 策略。
2.使用该模式将类的业务逻辑与算法的实现细节隔离开来,这些算法在 逻辑上下文中可能不那么重要。
3.当你的类具有大量的条件运算符,并且在同一算法的不同变体之间切 换时,请使用此模式
优点:
1.可以将算法的实现细节与使用它的代码隔离开来。
2.符合开闭原则