设计原则:请重新审视“多重继承”,找机会拥抱一下“掺入(Mixin)”
2013-04-25 07:53
363 查看
名称解释
多重继承:我没有使用多重继承的经验,因此这里不多说,大学学的C++,可惜没有学好。Mixin:一个Mixin是一个方法和属性的集合,不同的语言提供的实现机制不一样。类型定义的时候可以声明他想包含的Mixin(可以是多个),这些Mixin包含的方法会成为类型的一部分。
使用动机
代码复用 AND 运行时不改变。
Mixin是推论,MixinTarget是定理。如:C#的IEnumerable(MixinTarget)只包含一个方法,根据这个方法(定理)Enumerable(Mixin)扩展了N个方法(推论)。
示例(ExtJs4.2)
/// <reference path="../ext-all-debug-w-comments.js" /> Ext.define('Enjoyable', { play: function () { console.log(this.getName() + '-play'); } }); Ext.define('Workable', { work: function () { console.log(this.getName() + '-work'); } }); Ext.define('User', { mixins: { 'enjoyable': 'Enjoyable', 'workable': 'Workable' }, config: { name: 'unknow' }, constructor: function () { var me = this; me.initConfig(arguments); }, eat: function () { for (var i = 0; i < arguments.length; i++) { console.log(arguments[i]); } } }); var user = Ext.create('User'); user.setName('段光伟'); user.play(); user.work();
示例(C#扩展方法)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MixinDemo { public class User { public string Name { get; set; } } public static class Enjoyable { public static void Play(this User user) { Console.WriteLine(user.Name + "-play"); } } public static class Workable { public static void Work(this User user) { Console.WriteLine(user.Name + "-work"); } } }
示例(C#动态代理)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Castle.DynamicProxy; using Castle.DynamicProxy.Generators; namespace MixinStudy { class Program { static void Main(string[] args) { var proxy = Factory.Create<User>(); proxy.Id = Guid.NewGuid(); proxy.Name = "段光伟"; (proxy as ITeacher).Teach(); (proxy as IFather).Play(); } } [Mixin(typeof(Teacher))] [Mixin(typeof(Father))] public class User { public virtual Guid Id { get; set; } public virtual string Name { get; set; } } public interface ITeacher { User User { get; set; } void Teach(); } public class Teacher : ITeacher { [MixinTarget] public User User { get; set; } public void Teach() { Console.WriteLine("我教你读书吧:" + this.User.Name); } } public interface IFather { User User { get; set; } void Play(); } public class Father : IFather { [MixinTarget] public User User { get; set; } public void Play() { Console.WriteLine("我陪你玩吧:" + this.User.Name); } } public static class Factory { public static T Create<T>(params object[] args) where T : class { var generator = new ProxyGenerator(); var options = new ProxyGenerationOptions(); foreach (MixinAttribute attribute in typeof(User).GetCustomAttributes(true)) { var mixin = Activator.CreateInstance(attribute.MixinType); options.AddMixinInstance(mixin); } var target = Activator.CreateInstance(typeof(T), args) as T; var proxy = generator.CreateClassProxyWithTarget(target, options); foreach (var mixin in options.MixinsAsArray()) { foreach (var property in mixin.GetType().GetProperties()) { if (property.GetCustomAttributes(typeof(MixinTargetAttribute), true).Any()) { property.SetValue(mixin, target); } } } return proxy; } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class MixinAttribute : Attribute { public MixinAttribute(Type mixinType) { this.MixinType = mixinType; } public Type MixinType { get; set; } } public class MixinTargetAttribute : Attribute { } }
示例(C++)
class Enjoyable { public: Enjoyable(void); ~Enjoyable(void); void Play(); virtual string GetName() = 0; }; class Workable { public: Workable(void); ~Workable(void); void Work(); virtual string GetName() = 0; }; class User: public Enjoyable, public Workable { public: User(void); ~User(void); private: string name; public: string GetName(); void SetName(string name); }; User::User(void) { } User::~User(void) { } string User::GetName() { return this->name; } void User::SetName(string name) { this->name = name; } void Enjoyable::Play(){ cout << ( this->GetName() + "play"); } void Workable::Work(){ cout << ( this->GetName() + "work"); }
示例(Ruby)
module Enjoyable def play puts(self.name + "-play") end end module Workable def work puts(self.name + "-work") end end class User include Enjoyable, Workable attr_accessor :name end user = User.new user.name = "段光伟" user.play user.work
代码示例(Java的Qi4j)
示例地址:http://qi4j.org/latest/two-minutes-intro.html代码示例(Python)
user.pyclass User(): def __init__(self): self.name = "unkwnow" from Enjoyable import play from Workable import work def getName(self): return self.name def setName(self, name): self.name = name user = User() user.setName("段光伟") user.play() user.work()
Enjoyable.py
def play(self): print(self.name + "-play")
Workable.py
def work(self): print(self.name + "-work")
备注
在学习一门语言的时候,如何模拟Mixin是我必须思考的一个东西。相关文章推荐
- 谈一下响应式网站的设计原则
- 设计模式MIxin 特殊的多继承
- 一文带你重新审视CAP理论与分布式系统设计
- 设计原则--重新读来
- 重新审视演进式设计
- 继承接口面向对象的7个设计原则
- 重新审视演进式设计
- 设计原则:不要为了复用而使用继承
- Ajax in action[第一部分 重新审视WEB设计]
- 是时候重新审视正在流行的卡片设计趋势了!
- 七年过去了,让我们重新审视一下Twitter
- 设计原则:和继承相比,更推荐使用组合
- Python基础-MixIn设计-多重继承
- 设计模式之开放-封闭原则(引申出Objective-C中继承、Category、Protocol三者的区别,这点面试常问)
- 面向对象设计原则七 - 组合优先于继承
- UI组件设计方案: 审视类继承带来的复杂性(层次化),审视解除类继承带来的结构扁平化(易懂)
- 面向对象设计原则—高内聚、低耦合。多聚合、少继承
- 20年过去了,重新审视设计模式
- 记录一下----关于设计模式和面向对象设计原则
- 重新审视教师工作量部分设计