培训笔记之java 五

1.接口类:interface
接口类只有成员声明,但没有实现的类,接口类声明的方法必须是public,其默认值也是public.
2.具体类和接口类:
具体类class不能继承(exteds)interface类,只能实现implements.即接口只能实现。
注意: <1>.声明接口时不能加{},因为一旦加{}就相当于你实现了这个方法了,是错误的,直接加;号即可。
      <2>.一旦实现接口时,必须实现其所有方法。
      <3>.具体类可以实现多个接口,而不限于只实现一个接口。用","号分离即可;
3.抽象类Abstract
 抽象类介于具体类和接口之间,可以部分实现方法。在类前用abstract来声明,并且可以像具体类一样实现一个接口,但可以有选择性的实现接口的方法,而不用全部实现。且抽像类可以被继承。且子类必须实现抽象类中所没有实现的接口中的方法,并且可以不实现抽象类的方法或对抽象类的方法进行重载。,但必须实现接口里的方法。
在C++里面实现多继承会产生二异性,但在java里,如果同时实现两个接口,并不存在二异性,因为java接口里声明的都是空方法,而C++里的方法是有实体的,所以接口不会产生二异性,而C++会。
接口也可以继承,子类可以继承父类的方法的声明。

4.OO设计原则:
 在软件开发中唯一不变的就是变化。任何系统在其生命周期中都会发生变化。如果我们希望开发出的系统不会在第一版本后就被抛弃,那么我们就必须牢牢记住这一点。
 软件领域模块设计知道原则:
  High cohesion,Low coupling 高内聚,低耦合。
目前OO的设计的原则主要有以下几类:
 <1>.SRP,Single Responsibility Principle  单一职责原则(高内聚)
  对一个类而言,应该仅有一个引起它变化的原因。
  需求的变化就是功能的变化;反映到类上就是职责变化,如果一个类的职责过多,那么这些职责就会互相依赖,一个职责的变化可能会影响到另一个职责的履行。其实OOD实质就是合理地进行类地职责分配。
 <2>.OCP,Open-Closed Principle 开闭原则
  Software entities should be open for extension,but closed for modification
  是OO设计地第一原则。它因该对拓展是开放地,但是对修改应该是关闭地。即我地软件行为可以被扩展,但是我的软件不能被修改。
 <3>.LSP,Liskov Substitution Principle 里氏代换原则
  If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behaviour of P is unchanged when o1 is substituted for o2 then S is a subtype of T.
           — Barbara Liskov

 里氏代换原则:若对于每一个类型S的对象o1,都存在一个类型T的对象o2,使得在所有针对T编写得程序P中,用o1替换o2后,程序P的行为功能不变,则S是T的子类型。
 换句话说:任何基类出现得地方,子类一定可以出现。由父类承担得职责,子类一定可以承担,反之不行。

 <4>.DIP,Dependency Inversion Principle 依赖倒转原则

 a.High-level modules should not depend on low-level modules.Both should depend on abstractions
 b.Abstractions should not depend on details.Detils should depend on abstractions.

 要以来于抽象,不要依赖于具体。高层的模块不要依赖于底层的模块,都要依赖于抽象。(可以理解为在企业中只依赖于规则,而不依赖于老板,这样能实现即使没有老板,公司也照样运行,如果老本没了公司就跨了,那么就是失败的。)

        Program to an interface,not an implementation

 针对接口编程,而不要面向实现变成,注意这里的接口不是java里的接口类

 DIP原则是Framework设计的核心原则 OCP是目标,DIP是实现目标的方法

 依赖即耦合:零耦合(不相关的类),具体耦合(一个类改了之后另一类必须改(方法调用关系),这种耦合是良性的.但是在子类里面调用父类的方法,不是良性的。父类功能变换影响了子类的功能。正确方法是子类可以重写父类方法),抽象耦合(有实现关系的耦合)。

 Dip原则谑称"好莱坞原则":Hollywood Principle ,Don't call us,we'll call you.即依赖倒转。这种依赖是需要时才建立,即这种依赖是动态的而不是静态的。

 控制反转:IOC Inversion of Control
 依赖驻入:Dependency Injection
 Martin Flower

 <5>.ISP,Interface Segregation Principle 接口隔离原则ISP
 接口隔离原则ISP:不应该强迫客户依赖于他们不用的方法,接口属于客户,不属于它所在的类层次结构。(例如继承使,子类继承了父类的所有方法,但有的方法子类不需要,是被父类强迫的。)接口里的方法要尽可能少。大的接口可以分割成小接口。但是工具类可以实现多个方法。越多越好。
 
 <6>.CARP,Composition/Aggregation Principle 组合/聚合复用原则
 组合/聚合复用原则CARP:在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用自己的目的。另一种说法:Favor Composition over Inheritance  尽量使用类的组合复用,尽量不要使用继承复用。
 组合要比继承好的多。
 组合和聚合的区别:组合关系紧密性强于聚合关系,组合意味着生命周期相同,而聚合不一定。
 注意在多个小对象组合成一个大对象,在销毁时一定要把其它的对象也销毁。

 <7>.LoD,Law of Demeter  迪米特法则
 又叫做最少知识原则:Least Knowledge Principle,LKP:一个对象应当对其他对象有尽可能少的了解。迪米特法则要求任何一个软件实体,除非绝对需要,不然不要与外界通信。即使必须进行通信,也应当尽量限制通信的广度和深度

下面的程序是对昨天的程序的改进,用到了上面的一些原则,请读者参考。提供了对数据的增,删,改功能。

首先建立如下的几个包:
com.control :存放逻辑控制类:Controller
com.data    :存放数据类:    User
com.factory :存放工厂类:    UserFactory
com.op      :存放操作类:    AddUser,DeleteUser,UpdateUser 应用单一职责原则SRP,每个类只实现一个功能
com.superclass: 存放超类或接口: UserOp
还要建一个资源文件:command.properties

以下是各个类的源文件:
类:Controller
package com.control;

import javax.swing.JOptionPane;

import com.data.User;
import com.factory.*;

public class Controller {
 
 public static void main(String[] args) {  
  User user=new User();
  user.setUserId("1");
  user.setUserName("mc");
  user.setPassWord("ly");
  String command=JOptionPane.showInputDialog("请输入您要进行的操作!");
  UserFactory.getUserOp(command).execute(user);
 }

}
package com.data;
类:    User
public class User {
 private String userId = null;

 private String userName = null;

 private String passWord = null;

 //...set get方法
 public String toString() {
  return userId+userName+passWord;
 }

}
类:    UserFactory
package com.factory;

import java.util.ResourceBundle;

import com.superclass.UserOp;

public class UserFactory {

 public static UserOp getUserOp(String command) {
  
  UserOp userOp=null;
  
  ResourceBundle resource = ResourceBundle.getBundle("command");
  String className=resource.getString(command);
  try {
    userOp=(UserOp)Class.forName(className).newInstance(); //  
  } catch (InstantiationException e) {   
   e.printStackTrace();
  } catch (IllegalAccessException e) {   
   e.printStackTrace();
  } catch (ClassNotFoundException e) {   
   e.printStackTrace();
  }
  return userOp;
 }

}
类:    AddUser
package com.op;

import com.data.User;
import com.superclass.UserOp;

public class AddUser implements UserOp {

 public int execute(User user) {
  int succ = 0;  
  System.out.println("添加用户"+user.getUserName()+"成功");
  succ = 1;
  return succ;  
 }

}
类:    DeleteUser
package com.op;

import com.data.User;
import com.superclass.UserOp;

public class DeleteUser implements UserOp {

 public int execute(User user) {
  int succ = 0;
  System.out.println("删除用户"+user.getUserName()+"成功");
  succ = 1;
  return succ;  
 }

}
类:    UpdateUser
package com.op;

import com.data.User;
import com.superclass.UserOp;

public class UpdateUser implements UserOp {

 public int execute(User user) {
  int succ = 0;  
  System.out.println("用户"+user.getUserName()+"更新成功");
  succ = 1;
  return succ;  
 }

}
接口: UserOp
package com.superclass;

import com.data.User;

public interface UserOp {
 public int execute(User user);
}
资源文件里的内容为:
a = com.op.AddUser
d = com.op.DeleteUser
u = com.op.UpdateUser

这样,运行程序时,分别输入a,d,u则可以分别实现添加、删除、更新用户。所有的操作都只执行同一个方法。
这个程序很典型的用到了上面所提的多种模式。简单的实现了软件的行为可以被扩展;但是代码不能被修改!

比如这个项目我要增加一个登录功能,那么我不用修改代码,只要在com.op中新建一个UserLogin类(要实现UserOp接口),在资源文件中加入如下一行:login=UserLogin;
其中UserLogin的代码如下
package com.op;

import com.data.User;
import com.superclass.UserOp;

public class UserLogin implements UserOp {

 public int execute(User user) {  
  int succ = 0; 
  if(!user.getUserName().equals("mc")){
   System.out.println("用户"+user.getUserName()+"登录失败!");
   return succ;
  }
  if(!(user.getPassWord().equals("ly"))){
   System.out.println("用户"+user.getUserName()+"密码错误!");
   return succ;
  }
  System.out.println("用户"+user.getUserName()+"登录成功");
  succ = 1;
  return succ; 
 }

}
那么你在运行程序时输入login则程序会自动执行登录算法。
在这个例子中,应用了如下原则:
 单一职责原则(高内聚)SRP(除了Controller类,它是作为控制类来用的)。
 开闭原则 OCP 一个Controller类,一个UserFactory类,把原来的if语句改成配置文件了,并且使用Class.forName消除了与子类的关系,动态生成类.
 里氏代换原则 LSP: 只要父类可以实现的用子类即可替换。反之不可。:主要是在Controller中,用父类实现的方法用子类能够替换(execute方法),但是在UserFactory中,用到的父类的地方用子类却不能替换。
 依赖倒转原则 DIP(谑称“好莱坞原则”) 从Controller中可以看出,在原来中都是直接依赖关系,但本程序中这中依赖关系在编译时体现不出来,可以实现动态的改变类之间的关系。
 接口隔离原则ISP: 这里没有多个接口,但是我们在接口里只写了一个方法,当然也可以写三个方法,但是这样的话会强迫客户接受不需要的方法。所以要么拆分接口,要么合并方法。
 组合/聚合复用原则CARP:本例中没有直接体现。但可以举个例子,比如我现在要添加一个Admin类,那么可以这么写:
public class Admin{
 private User user=new User();
 private String userName
 public String getUserName(){
  return user.getUserName();
 }
 public void setUserName(String userName){
  this.userName=userName
 }
}这样做Admin有选择权,可以选择用和不用。这里只是个简单的例子,尽量使用委托方式而不是继承。

 迪米特法则LoD:在这里的Controller原来时与很多类建立了关系,但现在只和一个工厂类建立了关系,减少了与外界的接触。

缺点:读完上面程序您可能会问:那查询那?怎么没有相关操作那。本程序没有实现查询,因为查询返回的是User类型,且查询参数也不一样,我们这里只能返回int型,且参数为user,而查询必须返回一个user集合,甚至是集合类,参数也只需要userId即可,所以上述的接口文件必须要增加一个新方法才行,但那样的话就违背了上面的接口隔离原则,难到为了实现isp原则我们还的新建个接口,但如果建了新接口,那么在工厂类中就得加入语句判断,这又违反了单一职责等原则,那么有没有什么一举两得的放法那!!!请读者自己思考。将在下次公布。

5.根据上面的问题,。
成员变量是组合,如果操作其他类的话就有可能是聚合了。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值