接口进阶:接口子类实例化和策略模式

几种类型的实例化

  • 抽象类 - 不可以直接实例化
  • 同样纯抽象类 - 接口,也不可以直接实例化
  • 使用虚方法的类(有点半抽象的感觉),子类可以有选择的重写或者不重写

使用虚方法【virtual】的类:
子类可以有选择的重写或者不重写,直接继承后,不重写,直接调用基类代码,重写使用override关键字。
重写后调用基类代码:base.function();
++++++++++++++++++++++++++++++++++++++++++++++++++++++
虚方法必须有定义和实现,不然会触发 - CS0501的错误。

示例生成CS 0501:

“成员函数”必须声明一个主体,因为它没有标记为抽象、外部或部分。 非抽象方法必须有实现。

// CS0501.cs  
// compile with: /target:library  
public class clx  
{  
   public void f();   // CS0501 declared but not defined  
   public void g() {}   // OK  
}  

实例化场景

  • 抽象类被作为基类使用后,派生类可以进行实例化,此时已经实现定义,可以实例化。

  • 基类声明接口对象后,无法直接实例化,但是可以通过外部的类进行继承实现,在子类通过方法直接赋值给此对象 -【通过接口实现多态】-【面向接口编程】-【策略模式】

策略模式案例

增加了代码可重用性,易扩展性,可维护性。

设计原则:要针对接口编程,不要针对实现编程。

  • 针对实现编程:
Dog dog = new Dog();
dog.Dark();
  • 针对接口/父类编程:
Animal animal = new Dog();
animal.MakeSound()

只有在在运行是才指定具体实现的对象,我们一点不管他是什么类型,我们只关心他正确的实现MakeSound方法就好了。

下边是鸭子行为的接口和此行为的具体类。

  • 定义接口-通用的模块
// 所有飞行行为的接口
public interface IFlyBehaviour
{
    void Fly();
}
// 所有叫行为的接口
public interface IQuackBehaviour
{
    void Quack();
}
  • 实现接口-多态

// 使用翅膀飞
public class FlyWithWings : IFlyBehaviour
{
    public void Fly()
    {
        //使用翅膀飞
        Debug.Log("使用翅膀飞");
    }
}
// 不会飞
public class FlyNoWay : IFlyBehaviour
{
    public void Fly()
    {
        //什么都不做,不能飞
        Debug.Log("什么都不做,不能飞");
    }
}
// 呱呱叫
public class Quack : IQuackBehaviour
{
    public void Quack()
    {
        //呱呱的叫
        Debug.Log("呱呱的叫");
    }
}
// 吱吱叫
public class Squeak : IQuackBehaviour
{
    public void Quack()
    {
        //吱吱的叫
        Debug.Log("吱吱的叫");
    }
}
// 不会叫
public class MuteQuack : IQuackBehaviour
{
    public void Quack()
    {
        //什么都不做,不会叫
        Debug.Log("什么都不做,不会叫");
    }
}

下面是鸭子的抽象类,关于抽象类需要注意以下几点:
① 抽象类只能用做其他类的基类。
② 抽象类可以包含抽象成员和普通的非抽象成员。
③ 抽象可以继承自另一个抽象类
④ 所有抽象类的成员必须使用override关键字实现。
⑤ 抽象类不能创建实例。

  • 定义基类和接口对象
// 鸭子抽象类
public abstract class SuperNewDuck
{
    public IFlyBehaviour flyBehaviour;
    public IQuackBehaviour quackBehaviour;

    //必须要实现的可以考虑抽象方法
    public abstract void Swim();
    public abstract void Display();

    public void PerformFly()
    {
        //鸭子不会亲自处理飞的行为,而是委托给flyBehaviour引用的对象
        flyBehaviour.Fly();
    }

    public void PerformQuack()
    {
        //鸭子不会亲自处理呱呱叫的行为,而是委托给quackBehaviour引用的对象
        quackBehaviour.Quack();
    }

    public void SetFlyBehaviour(IFlyBehaviour flyType)
    {
        flyBehaviour = flyType;
    }

    public void SetQuackBehaviour(IQuackBehaviour quackType)
    {
        quackBehaviour = quackType;
    }
}
  • 下面是具体的鸭子派生类
// 野鸭
public class SuperMallardDuck : SuperNewDuck
{
    public SuperMallardDuck()
    {
        flyBehaviour = new FlyWithWings();
        quackBehaviour = new Quack();
    }

    public override void Display()
    {
        Debug.Log("外观是野鸭");
    }

    public override void Swim()
    {
        Debug.Log("在花式游泳");
    }
}

// 木头鸭
public class SuperMecoyDuck : SuperNewDuck
{
    public SuperMecoyDuck ()
    {
        flyBehaviour = new FlyNoWay();
        quackBehaviour = new MuteQuack();
    }

    public override void Display()
    {
        Debug.Log("外观是木头鸭");
    }

    public override void Swim()
    {
        Debug.Log("在正常游泳");
    }
}
//Unity测试代码...
public class DuckSimulator : MonoBehaviour
{
    private void Start()
    {
        //实例一只野鸭
        SuperNewDuck superMallardDuck = new SuperMallardDuck();

        superMallardDuck.Display();
        superMallardDuck.Swim();
        superMallardDuck.PerformFly();
        superMallardDuck.PerformQuack();

        Debug.Log("--------动态改变鸭子飞行行为-----------");

        //运行时改变飞行状态
        superMallardDuck.SetFlyBehaviour(new FlyWithWings());
        superMallardDuck.PerformFly();
    }
}

这时新需求来了,要增加一只超级鸭子,他使用的是导弹飞行器,你怎么办?
① 添加FlyWithRocket类实现自IFlyBehaviour接口
② 给超级鸭子创建FlyWithRocket行为

设计原则:多用组合,少用继承。这里的少用并不是不用。

此设计模式名称:策略模式,他定义了算法族,分别封装起来。让他们之间可以互相替换,此算法独立于使用算法的客户。

设计谜题

设计谜题:
① 现在想象一下你要做一款动作冒险类(ACT)的游戏
② 有一个主角会使用武器
③ 但是同一时刻只能使用一种武器
④ 武器之间可以随意的切换
请你仔细想想你该怎么设计你的代码的架构并运用到游戏中去…

鬼泣5
好,现在来说说想法:
① 首先想到的应该是武器的抽象,将所有武器抽象成一个名为IWeaponBehaviour的接口,让其他的武器去实现这个接口,已达到动态改变行为的目的
② 然后就是角色的父类,具有配备武器的属性,战斗的属性,动态改变武器类型的属性
③ 你的代码结构可能如下

/// <summary>
/// 角色父类
/// </summary>
public class BaseCharacter
{
    protected IWeaponBehaviour weaponBehaviour;   //角色配备武器的属性

    public virtual void fight() { }   //战斗

    public void SetWeapon(IWeaponBehaviour w)   //切换武器
    {
        weaponBehaviour = w;
    }
}
/// <summary>
/// 武器行为接口
/// </summary>
public interface IWeaponBehaviour
{
    void useWeapon();
}
using UnityEngine;

/// <summary>
/// 武器巴雷特狙击枪
/// </summary>
public class Barrett : IWeaponBehaviour
{
    public void useWeapon()
    {
        Debug.Log("使用巴雷特狙击枪");
    }
}
using UnityEngine;

/// <summary>
/// 武器加特林
/// </summary>
public class Gatling : IWeaponBehaviour
{
    public void useWeapon()
    {
        Debug.Log("使用武器加特灵机关枪");
    }
}
using UnityEngine;

/// <summary>
/// 武器石头
/// </summary>
public class Stone : IWeaponBehaviour
{
    public void useWeapon()
    {
        Debug.Log("使用石头攻击");
    }
}
using UnityEngine;

/// <summary>
/// 武器剑
/// </summary>
public class Sword : IWeaponBehaviour
{
    public void useWeapon()
    {
        Debug.Log("使用剑");
    }
}
/// <summary>
/// 角色皇帝
/// </summary>
public class King : BaseCharacter
{
    public King()
    {
        weaponBehaviour = new Barrett();
    }

    public override void fight()
    {
        weaponBehaviour.useWeapon();
    }
}
/// <summary>
/// 角色皇后
/// </summary>
public class Queen : BaseCharacter
{
    public Queen()
    {
        weaponBehaviour = new Gatling();
    }

    public override void fight()
    {
        weaponBehaviour.useWeapon();
    }
}
/// <summary>
/// 角色骑士
/// </summary>
public class Knight : BaseCharacter
{
    public Knight()
    {
        weaponBehaviour = new Sword();
    }

    public override void fight()
    {
        weaponBehaviour.useWeapon();
    }
}
/// <summary>
/// 角色侏儒(或者叫哥布林哈哈)
/// </summary>
public class Troll : BaseCharacter
{
    public Troll()
    {
        weaponBehaviour = new Stone();
    }

    public override void fight()
    {
        weaponBehaviour.useWeapon();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WarSimulator : MonoBehaviour
{
    void Start()
    {
        BaseCharacter king = new King();
        BaseCharacter queen = new Queen();

        king.fight();
        king.SetWeapon(new Sword());
        king.fight();

        Debug.Log("---------分割线----------");

        queen.fight();
    }
}

最后再来复习一下
① 此设计模式名为策略模式
② 其核心设计思想是封装可互相替换的算法和策略,每一个算法都独立于使用算法的客户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值