组合和继承是一样的吗? 如果我想实现组合模式,我如何在Java中做到这一点?
当前回答
组合和继承是一样的吗?
它们不一样。
组合:它允许以对象的单个实例的方式处理一组对象。组合的目的是将对象“组合”成树状结构,以表示部分-整体层次结构
继承:类从其所有超类继承字段和方法,无论是直接的还是间接的。子类可以覆盖它继承的方法,也可以隐藏它继承的字段或方法。
如果我想实现组合模式,我如何在Java中做到这一点?
维基百科的文章足以在java中实现复合模式。
主要参与者:
组件:
是所有组件的抽象,包括复合组件吗 声明组合中对象的接口
叶:
表示组合中的叶对象 实现所有组件方法
复合材料:
表示一个复合组件(有子组件) 实现操作子节点的方法 实现所有Component方法,通常是将它们委托给其子方法
理解Composite模式的代码示例:
import java.util.List;
import java.util.ArrayList;
interface Part{
public double getPrice();
public String getName();
}
class Engine implements Part{
String name;
double price;
public Engine(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Trunk implements Part{
String name;
double price;
public Trunk(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Body implements Part{
String name;
double price;
public Body(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Car implements Part{
List<Part> parts;
String name;
public Car(String name){
this.name = name;
parts = new ArrayList<Part>();
}
public void addPart(Part part){
parts.add(part);
}
public String getName(){
return name;
}
public String getPartNames(){
StringBuilder sb = new StringBuilder();
for ( Part part: parts){
sb.append(part.getName()).append(" ");
}
return sb.toString();
}
public double getPrice(){
double price = 0;
for ( Part part: parts){
price += part.getPrice();
}
return price;
}
}
public class CompositeDemo{
public static void main(String args[]){
Part engine = new Engine("DiselEngine",15000);
Part trunk = new Trunk("Trunk",10000);
Part body = new Body("Body",12000);
Car car = new Car("Innova");
car.addPart(engine);
car.addPart(trunk);
car.addPart(body);
double price = car.getPrice();
System.out.println("Car name:"+car.getName());
System.out.println("Car parts:"+car.getPartNames());
System.out.println("Car price:"+car.getPrice());
}
}
输出:
Car name:Innova
Car parts:DiselEngine Trunk Body
Car price:37000.0
解释:
Part是一片叶子 汽车包含许多部件 汽车的不同部分已经添加到car中 汽车价格=(各部件价格)之和
关于组合和继承的利弊,请参考下面的问题。
喜欢组合而不是继承?
其他回答
继承Vs组合。
继承和组合都用于类行为的可重用性和扩展。
继承主要用在IS-A一类算法编程模型中,关系类型是指相似类型的对象。的例子。
吸尘器是一辆车 Safari是一辆车
这些是Car家族的。
Composition表示HAS-A关系类型。它显示了一个对象的能力,如Duster有五个齿轮,Safari有四个齿轮等。每当我们需要扩展现有类的能力时,就使用复合。例如,我们需要在Duster对象中添加一个齿轮,然后我们必须创建一个齿轮对象,并将其组合到Duster对象中。
除非所有派生类都需要这些功能,否则不应该对基类进行更改。对于这个场景,我们应该使用Composition。如
由类B派生
类A由类C派生
类A由类D派生。
当我们在类A中添加任何功能时,即使类C和类D不需要这些功能,它也可以用于所有子类。对于这个场景,我们需要为这些功能创建一个单独的类,并将其组合到所需的类中(这里是类B)。
下面是例子:
// This is a base class
public abstract class Car
{
//Define prototype
public abstract void color();
public void Gear() {
Console.WriteLine("Car has a four Gear");
}
}
// Here is the use of inheritence
// This Desire class have four gears.
// But we need to add one more gear that is Neutral gear.
public class Desire : Car
{
Neutral obj = null;
public Desire()
{
// Here we are incorporating neutral gear(It is the use of composition).
// Now this class would have five gear.
obj = new Neutral();
obj.NeutralGear();
}
public override void color()
{
Console.WriteLine("This is a white color car");
}
}
// This Safari class have four gears and it is not required the neutral
// gear and hence we don't need to compose here.
public class Safari :Car{
public Safari()
{ }
public override void color()
{
Console.WriteLine("This is a red color car");
}
}
// This class represents the neutral gear and it would be used as a composition.
public class Neutral {
public void NeutralGear() {
Console.WriteLine("This is a Neutral Gear");
}
}
两个类之间的继承,其中一个类扩展了另一个类,建立了“IS A”关系。
另一端的组合包含类中另一个类的实例,建立了“Has A”关系。组合在java中是很有用的,因为它在技术上便于多重继承。
构图是指某物由不同的部分组成,并且它与这些部分之间有很强的关系。如果主体死亡,其他部分也会死亡,他们就不能拥有自己的生命。一个粗略的例子就是人体。取出心脏,其他部分就会消失。
继承就是你取已经存在的东西并使用它。没有很强的关系。一个人可以继承他父亲的财产,但他也可以不继承。
我不知道Java,所以我不能提供一个例子,但我可以提供一个概念的解释。
继承意味着重用一个类的完整功能,在这里,我的类必须使用超类的所有方法,我的类将与超类titely耦合,在继承的情况下,代码将在两个类中重复。
但是当我们用作文与其他班级进行交流时,我们可以克服这些问题。复合是将另一个类的属性声明到我们想要与之对话的类中。我们想从那个类中得到什么功能可以通过使用那个属性来实现。
遗产怎么会是危险的?
让我们举个例子
public class X{
public void do(){
}
}
Public Class Y extends X{
public void work(){
do();
}
}
1)正如上面的代码所示,类Y与类X具有很强的耦合性。如果超类X发生任何变化,Y可能会急剧断裂。假设在未来的类X中实现了一个具有以下签名的方法work
public int work(){
}
改变是在类X中完成的,但它将使类Y不可编译。所以这种依赖可以上升到任何程度,这是非常危险的。每次超类都可能对其所有子类中的代码没有完全可见性,子类可能会一直注意到在超类中发生了什么。因此,我们需要避免这种强而不必要的耦合。
合成如何解决这个问题?
让我们复习一下同样的例子
public class X{
public void do(){
}
}
Public Class Y{
X x = new X();
public void work(){
x.do();
}
}
这里我们在Y类中创建X类的引用,并通过创建X类的实例调用X类的方法。 现在所有的强耦合都消失了。父类和子类现在彼此高度独立。类可以自由地进行更改,这在继承情况下是危险的。
2)第二个非常好的优点是它提供了方法调用的灵活性,例如:
class X implements R
{}
class Y implements R
{}
public class Test{
R r;
}
在测试类中使用r引用,我可以调用X类以及Y类的方法。这种灵活性在继承中是不存在的
3)另一个巨大优势:单元测试
public class X {
public void do(){
}
}
Public Class Y {
X x = new X();
public void work(){
x.do();
}
}
在上面的例子中,如果x实例的状态未知,可以用一些测试数据很容易地模拟出来,所有的方法都可以很容易地测试出来。这在继承中是完全不可能的,因为您严重依赖于超类来获取实例的状态并执行任何方法。
4)我们应该避免继承的另一个很好的理由是Java不支持多重继承。
让我们举个例子来理解这一点:
Public class Transaction {
Banking b;
public static void main(String a[])
{
b = new Deposit();
if(b.deposit()){
b = new Credit();
c.credit();
}
}
}
很高兴知道:
组合在运行时很容易实现,而继承在编译时提供其特性 组合也称为HAS-A关系,继承也称为is - a关系
因此,由于上述各种原因,要养成总是喜欢组合而不是继承的习惯。
推荐文章
- 面向方面编程与面向对象编程
- 指定的子节点已经有一个父节点。你必须先在子对象的父对象上调用removeView() (Android)
- 对于一个布尔字段,它的getter/setter的命名约定是什么?
- 如何获得当前屏幕方向?
- 如何在Android中渲染PDF文件
- super()失败,错误:TypeError "参数1必须是类型,而不是classobj"当父不继承对象
- 如何计算一个元素在列表中出现的次数
- c++中类似于java的instanceof
- 我如何解决错误“minCompileSdk(31)指定在一个依赖的AAR元数据”在本机Java或Kotlin?
- 如何POST表单数据与Spring RestTemplate?
- Mockito中检测到未完成的存根
- 我应该如何复制字符串在Java?
- “while(true)”循环有那么糟糕吗?
- 这个方法签名中的省略号(…)是干什么用的?
- Java:如何测试调用System.exit()的方法?