设计模式实际上就六个字:高内聚,低耦合
一、设计模式的六大原则
单一职责:
-
接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。 -
最少知道原则,又称迪米特法则(Demeter Principle)
最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
规范继承:
-
依赖倒转原则(Dependence Inversion Principle)
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。 -
里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
保持稳定:
-
合成复用原则(Composite Reuse Principle)
合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承,继承的耦合性太强。给父类添加内容时,会附带着给子类也添加内容,而有的时候子类不想要这些东西。 -
开闭原则(Open Close Principle)
开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
二、相似模式的比较(23种设计模式)
推荐文章:《Java中的23种设计模式详解》
1. 适配器模式和装饰器模式的区别
- 适配器模式:天生有两个端(适配类与被适配类不是继承自不同的接口),一端有需求,一端提供需求,两端的需求一般是不一致的。
- 装饰器模式:只有一个端(装饰类与被装饰类继承自同一个接口),但是可以有好多层,一层一层美化自己。
2. 装饰器模式和代理模式的区别
- 装饰器模式:聚合(生产好对象,再传给装饰器,不负责生命周期)
- 代理模式:组合(直接在代理里生产,负责生命周期)
3. 桥接模式与其他模式的区别
- 桥接模式:一端持有另一端,在保持一端不变的时候,另一端可以灵活的变化(有不同的实现);更通用的情况是,一端持有好几端,一端可以灵活的变化,好几端也可以各自灵活的变化,以实现不同的组合。
4. 组合模式与其他模式的区别
- 组合模式:整体与部分,体现为有规律的重复节点,如树、图等。
5. 享元模式与其他模式的区别
- 享元模式:共享池(池中的对象可以来自同一接口的不同子类),如线程池。
6. 中介者模式和外观模式的区别
- 中介者模式:实际上是总线模式。比如机场调度,各个飞机并不会互相通信,而是都和机场控制中心通信,这个例子里飞机是同一个类,等价的角色;比如租房子的时候,所有出租房子的人和所有要租房子的人也不会相互通信,而是都去中介那里注册,由中介进行匹配。
- 外观模式:实际上是对多个模块的组合封装。比如,给电脑通电,意味着给cpu通电,给内存通电,给硬盘通电。
三、J2EE设计模式
这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。
1. 过滤器模式
import java.util.ArrayList;
import java.util.List;
public class CriteriaPatternDemo {
public static void main(String[] args) {
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("Robert","Male", "Single"));
persons.add(new Person("John","Male", "Married"));
persons.add(new Person("Laura","Female", "Married"));
persons.add(new Person("Diana","Female", "Single"));
persons.add(new Person("Mike","Male", "Single"));
persons.add(new Person("Bobby","Male", "Single"));
// 男性过滤器
Criteria male = new CriteriaMale();
// 女性过滤器
Criteria female = new CriteriaFemale();
// 单身过滤器
Criteria single = new CriteriaSingle();
// 单身男性过滤器(组合过滤器)
Criteria singleMale = new AndCriteria(single, male);
// 单身或者女性过滤器(组合过滤器)
Criteria singleOrFemale = new OrCriteria(single, female);
System.out.println("Males: ");
printPersons(male.meetCriteria(persons));
System.out.println("\nFemales: ");
printPersons(female.meetCriteria(persons));
System.out.println("\nSingle Males: ");
printPersons(singleMale.meetCriteria(persons));
System.out.println("\nSingle Or Females: ");
printPersons(singleOrFemale.meetCriteria(persons));
}
public static void printPersons(List<Person> persons){
for (Person person : persons) {
System.out.println("Person : [ Name : " + person.getName()
+", Gender : " + person.getGender()
+", Marital Status : " + person.getMaritalStatus()
+" ]");
}
}
}
2. 空对象模式
public class CustomerFactory {
public static final String[] names = {"Rob", "Joe", "Julie"};
public static AbstractCustomer getCustomer(String name){
for (int i = 0; i < names.length; i++) {
if (names[i].equalsIgnoreCase(name)){
return new RealCustomer(name);
}
}
return new NullCustomer();
}
}
3. MVC模式
public class StudentController {
private Student model;
private StudentView view;
public StudentController(Student model, StudentView view){
this.model = model;
this.view = view;
}
public void setStudentName(String name){
model.setName(name);
}
public String getStudentName(){
return model.getName();
}
public void setStudentRollNo(String rollNo){
model.setRollNo(rollNo);
}
public String getStudentRollNo(){
return model.getRollNo();
}
public void updateView(){
view.printStudentDetails(model.getName(), model.getRollNo());
}
}
4. 业务代表模式
实际上是对工厂模式的进一步封装。
public class BusinessDelegate {
private BusinessLookUp lookupService = new BusinessLookUp();
private BusinessService businessService;
private String serviceType;
// 根据传入的serviceType决定businessService
public void setServiceType(String serviceType){
this.serviceType = serviceType;
}
// 不同的businessService执行不同的业务逻辑
public void doTask(){
businessService = lookupService.getBusinessService(serviceType);
businessService.doProcessing();
}
}
5. 组合实体模式
public class CompositeEntity {
private CoarseGrainedObject cgo = new CoarseGrainedObject();
public void setData(String data1, String data2){
cgo.setData(data1, data2);
}
public String[] getData(){
return cgo.getData();
}
}
public class Client {
private CompositeEntity compositeEntity = new CompositeEntity();
public void setData(String data1, String data2){
compositeEntity.setData(data1, data2);
}
public void printData(){
for (int i = 0; i < compositeEntity.getData().length; i++) {
System.out.println("Data: " + compositeEntity.getData()[i]);
}
}
}
6. 数据访问对象模式
public interface StudentDao {
public List<Student> getAllStudents();
public Student getStudent(int rollNo);
public void updateStudent(Student student);
public void deleteStudent(Student student);
}
public class StudentDaoImpl implements StudentDao {
//列表是当作一个数据库
List<Student> students;
public StudentDaoImpl(){
students = new ArrayList<Student>();
Student student1 = new Student("Robert",0);
Student student2 = new Student("John",1);
students.add(student1);
students.add(student2);
}
@Override
public void deleteStudent(Student student) {
students.remove(student.getRollNo());
System.out.println("Student: Roll No " + student.getRollNo()
+", deleted from database");
}
//从数据库中检索学生名单
@Override
public List<Student> getAllStudents() {
return students;
}
@Override
public Student getStudent(int rollNo) {
return students.get(rollNo);
}
@Override
public void updateStudent(Student student) {
students.get(student.getRollNo()).setName(student.getName());
System.out.println("Student: Roll No " + student.getRollNo()
+", updated in the database");
}
}
7. 前端控制器模式
public class FrontController {
private Dispatcher dispatcher;
public FrontController(){
dispatcher = new Dispatcher();
}
private boolean isAuthenticUser(){
System.out.println("User is authenticated successfully.");
return true;
}
private void trackRequest(String request){
System.out.println("Page requested: " + request);
}
public void dispatchRequest(String request){
//记录每一个请求
trackRequest(request);
//对用户进行身份验证
if(isAuthenticUser()){
dispatcher.dispatch(request);
}
}
}
public class Dispatcher {
private StudentView studentView;
private HomeView homeView;
public Dispatcher(){
studentView = new StudentView();
homeView = new HomeView();
}
public void dispatch(String request){
if(request.equalsIgnoreCase("STUDENT")){
studentView.show();
}else{
homeView.show();
}
}
}
8. 拦截过滤器模式
public class InterceptingFilterDemo {
public static void main(String[] args) {
FilterManager filterManager = new FilterManager(new Target());
filterManager.setFilter(new AuthenticationFilter());
filterManager.setFilter(new DebugFilter());
Client client = new Client();
client.setFilterManager(filterManager);
client.sendRequest("HOME");
}
}
public class FilterManager {
FilterChain filterChain;
public FilterManager(Target target){
filterChain = new FilterChain();
filterChain.setTarget(target);
}
public void setFilter(Filter filter){
filterChain.addFilter(filter);
}
public void filterRequest(String request){
filterChain.execute(request);
}
}
public class FilterChain {
private List<Filter> filters = new ArrayList<Filter>();
private Target target;
public void addFilter(Filter filter){
filters.add(filter);
}
public void execute(String request){
for (Filter filter : filters) {
filter.execute(request);
}
target.execute(request);
}
public void setTarget(Target target){
this.target = target;
}
}
9. 服务定位器模式——缓存模式
服务定位器模式(Service Locator Pattern)用在我们想使用 JNDI 查询定位各种服务的时候。考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术。在首次请求某个服务时,服务定位器在 JNDI 中查找服务,并缓存该服务对象。当再次请求相同的服务时,服务定位器会在它的缓存中查找,这样可以在很大程度上提高应用程序的性能。以下是这种设计模式的实体。
10. 传输对象模式
设计的不好……
还不如:让BO持有VO对象,以较少两个对象中的重复属性。