组合复用原则

转载请注明出处!!!http://blog.csdn.net/zhonghuan1992

         所有配套代码均在github上:https://github.com/ZHONGHuanGit/DesignPattern



跟着ZHONGHuan学习设计模式

组合复用原则







组合复用原则定义:

         在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,新的对象通过向这些对象的委派达到复用已有功能的目的

另外一种说法是:尽量使用(对象)组合,而非继承

 

那么组合和继承各自有什么特点,优缺点,为什么要有这样的优先呢!先来比较一下组合和继承。

组合 VS. 继承

组合复用的优点和缺点

组合

优点:

         1容器类仅能通过被包含对象的接口来对其进行访问。

         2“黑盒”复用,因为被包含对象的内部细节对外是不可见。

         3  封装性好。

         4  通过获取指向其它的具有相同类型的对象引用,可以在运行期间动态地定义(对象的)组合。

 

缺点:

         1  导致系统中的对象过多。

         2  为了能将多个不同的对象作为组合块(compositionblock)来使用,必须仔细地对接口进行定义。

 

继承

(类)继承是一种通过扩展一个已有对象的实现,从而获得新功能的复用方法。泛化类(超类)可以显式地捕获那些公共的属性和方法。特殊类(子类)则通过附加属性和方法来进行实现的扩展。

继承的优点和缺点

优点:

         1  容易进行新的实现,因为其大多数可继承而来。

         2 易于修改或扩展那些被复用的实现。

 

缺点:

         1  破坏了封装性,因为这会将父类的实现细节暴露给子类。

         2  “白盒”复用,因为父类的内部细节对于子类而言通常是可见的。

         3  当父类的实现更改时,子类也不得不会随之更改。

         4  从父类继承来的实现将不能在运行期间进行改变。

 

         要正确使用继承,必须透彻的理解里氏代换原则和Coad法则。里氏代换原则前面学习过,Coad法则由Peter Coad提出,总结了一些什么时候使用继承作为复用工具的条件。只有当以下的Coad条件全部被满足时,才应当使用继承关系:

         1       子类是超类的一个特殊种类,而不是超类的一个角色,也就是区分“Has-A”和“Is-A”。只有“Is-A”关系才符合继承关系,“Has-A”关系应当用组合来描述。

         2       永远不会出现需要将子类换成另外一个类的子类的情况。如果不能肯定将来是否会变成另外一个子类的话,就不要使用继承。

         3       子类具有扩展超类的责任,而不是具有置换调(override)或注销掉(Nullify)超类的责任。如果一个子类需要大量的置换掉超类的行为,那么这个类就不应该是这个超类的子类。

         4       只有在分类学角度上有意义时,才可以使用继承。不要从工具类继承。

 

         很多情况下,选择继承关系描述两个类之间的关系,是因为对继承关系的理解不够造成的。下面讨论 Is-A 和 Has-A 的区别。

Is-A 和 Has-A 区别:

         Is-A顾名思义,就是“是一个”,意思是一个类是另一个类的一种;Has-A是“有一个”,意思是一个类是另一个类的一部分。

         错误的使用继承而不是使用组合,就是把“Has-A”当做“Is-A”。

         考虑一下这样的情况。我们每个人都有一个身份,比如我是老师,你是学生,他是运动员。所以,加入要为这样的情况设计我们的类图。可能会是下面的情况。

        

         对应代码如下:

        

class Person
{
	public Person()
	{
	}
}

class Teacher extends Person
{
	public Teacher()
	{
		System.out.println("Iam a teacher.");
	}
}

class Student extends Person
{
	public Student()
	{
		System.out.println("Iam a student.");
	}
}

class Athlete extends Person
{
	public Athlete()
	{
		System.out.println("Iam a athlete");
	}
}

         但是这样的设计,会有问题。我们可以想想,每个人在现实生活中不单单只有一个身份,可能会有很多身份,比如我可以是一个学生,也可以是一名运动员,这并不是一个矛盾的事情。但是上面的设计,忽略了这个因素。导致每个人只有一种身份,这显然是不合理的。

所以,我们重新设计。请看下面的设计,遵循了组合复用原则。

        

代码如下:

 

class Person
{
	private Role role;

	public Person()
	{
	}

	public void setRole(Role role)
	{
		this.role = role;
	}

	public Role getRole()
         {
                   return role;
         }
}

interface Role
{

}

class Teacher implements Role
{
	public Teacher()
	{
		System.out.println("Iam a teacher.");
	}
}

class Student implements Role
{
	public Student()
	{
		System.out.println("Iam a student.");
	}
}

class Athlete implements Role
{
	public Athlete()
	{
		System.out.println("Iam a athlete");
	}
}

         由原来的聚合关系变为现在的组合关系。一个人现在可以有多重角色,在不同的情况下,我们可以给人物设置不同的角色。

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
非常好的问题,我可以回答。以下是 Java 设计并实现符合单一职责原则、里氏替换原则组合复用原则的计算器演示系统代码: ``` //符合单一职责原则: public class Calculator { public int calculate(int num1, int num2, String operator) { switch (operator) { case "+": return num1 + num2; case "-": return num1 - num2; case "*": return num1 * num2; case "/": return num1 / num2; default: throw new IllegalArgumentException("Invalid operator: " + operator); } } } //符合里氏替换原则: public class AdvancedCalculator extends Calculator{ public int square(int num) { return num * num; } public double sqrt(int num) { return Math.sqrt(num); } } //符合组合复用原则: public class CalculatorDemo { private final Calculator calculator; private final AdvancedCalculator advancedCalculator; public CalculatorDemo(Calculator calculator, AdvancedCalculator advancedCalculator) { this.calculator = calculator; this.advancedCalculator = advancedCalculator; } public void demo() { System.out.println(calculator.calculate(1, 2, "+")); System.out.println(calculator.calculate(3, 4, "-")); System.out.println(advancedCalculator.square(5)); System.out.println(advancedCalculator.sqrt(6)); } } ``` 这里的 Calculator 类负责基本的加减乘除计算,它只有一个明确的职责。AdvancedCalculator 类继承了 Calculator 类,它扩展了计算器的计算功能,同时还保持了基本计算器所具有的一些功能。而 CalculatorDemo 则组合了 Calculator 和 AdvancedCalculator 对象,展示了它们的基本和高级计算功能。这样,代码不仅简单易懂,而且易于扩展和维护,符合单一职责原则、里氏替换原则组合复用原则
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值