桥接模式
我走进她的房间,发现她正在看电视剧.
最近好像<觉醒年代>很火,大家都在看剧,她也一样,不过她说自从胡适出场之后,就不好看了,里面的人和胡适说话偶尔言语轻浮,而且胡适并没有起到很大的作用,不喜欢胡适.看着看着想弃剧了.
我想,有时候女人的第六感可真可怕,胡适确实不是什么好人,除了学历丰富之外,不能与李大钊陈独秀相提并论.
不过既然她都想弃剧了,那么我就问她点问题吧,是的,自从前几次和她讲了一些设计模式,她就表现得理解能力特别强,还能把设计模式串起来.所以现在我就是有问题就去问她,说不定她又会给我什么惊喜.
我直接就说:"我又遇到问题了".
她转过来问我:"怎么了?遇到什么问题了?"
我说:"代码设计上的问题"
她笑了笑说:"我还真没有想到,你会问我这个问题,我可对于你的这个一点都不会啊"
我说:"你少来了,你肯定比我聪明"
她说:"好吧,反正这电视剧也不好看了,你说说看?"
我说:"原来我有武器库的一个类,然后玩家可以选择若干种角色,一般来说一个角色的职业会有不通的武器,通过建立起2个大类,一个武器类,一个角色类,派生出子类,然后子类相互调用.但是最近我又想丰富一下玩法,就是可以转职.角色就可以使用其他的武器了,但是衍生出一个问题,类与类的调用就好乱."
她问:"怎么个乱法?数量不可控了吗?"
我回答:"是这样的,不管什么角色来使用武器的时候,一般都是这个角色的类来实例出武器的类,当角色跟换武器的时候,就更换实例出来的类."
她问:"你的意思是一个角色类中对于武器的实例是多选一是吗?如果增加一个武器,就要修改所有的角色类,如果增加一个角色就要再把所有的武器类都在角色类中声明,对吧?"
我说:"是的,这样结构性就被破坏了,牵一发而动全身,不是一个好的设计模式"
她想了一会儿,说:"那要是你把对于武器的选择写在父类中呢?子类只需要实现这个父类的方法,就可以实现选择武器的共了啊,哦,对,这样违反了开闭原则是吧?我记得你说过,一旦有修改父类的,那就是违反了开闭原则"
我笑了笑,说:"那个一般是说已经上线的,不再修改父类,在开发过程中是可以修改的,因为一开始编程谁也不知道会有什么功能"
她有点开心了,说:"那我这个方法可以用吗?"
我说:"那上线之后忽然又要加一个新角色,或者加一个武器呢?你还不是得要修改父类呀."
"哦,那你还说可以改."她有点儿泄气.
过来一会儿,她问我:"那我们应该该怎么办呢?"
我喜欢她说我们,就好像我做的这个游戏她也是开发者之一.
我说:"如果角色父类能引用武器父类,角色父类直接把武器类声明,角色子类在初始化的时候或者在需要更改武器的时候传入需要的武器子类就好了"
"你这是不用2个类私自联系对吧?但是我感觉这个只是在图上画的很简洁,其实实际上还是方法调用方法吧?"
我说:"实质当然还是方法调方法,但是省了许多的事情,借你电脑用下啦" 我接过她的电脑,开始我的代码编写
首先是Weapon的父类:
using UnityEngine; public abstract class Weapon { protected int damage = ; protected GameObject effect; protected string s = "武器"; protected void setValue(int damage,GameObject effect,string s) { this.damage = damage; this.effect = effect; this.s = s; } public void Shoot() { Debug.Log("damage:" + damage + "\n" + s); } }
我对她说:"基本的属性设置方法,一个设计方法,这是最最基本的功能,接下来我们写一个角色的父类:"
public abstract class Robot { private Weapon weapon = null; public void SetWeapon(Weapon this_weapon) { weapon = this_weapon; } protected void atc() { weapon.Shoot(); } public abstract void Attack(); }
"为啥叫robot啊?不能叫player吗?"她问.
"因为待会player是它的子类"我回答
接着我又给她解释道:"你看,这个角色的父类里面就有对武器的声明,那么角色的子类都能传这样的参数了,下面的atc方法用的就是子类传过来武器子类中的方法."
"感觉饶了好几次"她说.因为编程就是这样,绕来绕去的,当然,代码的优雅中并没有说道代码易读.
我说:"接下来看看它们的实现吧,还记得实现是啥意思不?"
Gun.cs
public class Gun : Weapon { void Gun_shoot() { setValue(, null, "gun"); Shoot(); } }
Player.cs
public class Player :Robot { public override void Attack() { atc(); } }
然后就来看看它们如何挂载调用吧
using UnityEngine; public class UsePlayer : MonoBehaviour { Player player = null; // Use this for initialization void Start () { player = new Player(); } // Update is called once per frame void Update () { if (Input.GetKeyDown(KeyCode.A)) { player.SetWeapon(new Gun()); player.Attack(); } if (Input.GetKeyDown(KeyCode.B)) { player.SetWeapon(new Gun()); player.Attack(); } } }
她说:"你这里写了2个一样的,按下A和按下B执行的是同一个方法"
我说:"因为我懒,不想写2个脚本,意思一下,当作换了武器,哈哈,看下效果吧"
"我有一个问题"她说,"那么如果我新增了一把抢,那么如果想要用的话,是不是所有的角色都得参照上面的代码写上player.SetWeapon(new Gun());"
"是的".我回答.
"那我感觉没有省什么事".
我说:"你注意哦,如果不这么写那么首先是角色子类实例枪类,这个没有问题,但是,如果我对于同一把抢,不同角色拿起来会有不用的效果呢?那该怎么办呢?"
她立马回答:"写上一个方法,子类可实现可不实现啊".
我愕然,她果然很聪明.我自愧不如,看来下次有不懂的,还是得问她.
建站 什么 虚拟主机 够用?这要看搭建的是什么类型的网站。比如个人博客类型的网...
【51CTO.com快译】 数据可视化工具不断发展,提供更强大的功能,同时改善可访问...
从 10.0.0 版开始,异步迭代器就出现在 Node 中了,在本文中,我们将讨论异步迭...
摘要 元旦期间 订单业务线 告知 推送系统 无法正常收发消息,作为推送系统维护者...
前提条件 请您在购买前确保已完成注册和充值。详细操作请参见 如何注册公有云管...
Docker生成新镜像版本的两种方式 There are two ways Docker can generate new m...
本文整理自直播《Hologres 数据导入/导出实践-王华峰(继儒)》 视频链接: https:/...
在Python语言中有如下3种方法: 成员方法 类方法(classmethod) 静态方法(staticm...
信息化2.0时代提出开展智慧教育创新发展行动。2019年2月,中共中央、国务院印发...
2021年3月24日,主题为《数据的世界,世界的数据》的星环科技2021春季新品发布会...