从“假如有以下几种价格10,20,50,请你代码实现将他们排序输出”看着设计模式中的策略模式

今天重温了一下策略模式,将自己的一些感悟与大家分享。。。本人只是技术渣渣,所理解的东西的难免会有很大的局限性甚至是错误,还请各位带着批判的眼光去看待。。。。不喜请勿吐槽

定义:策略模式属于设计模式中的对象行为型模式,它将用到的算法单独抽象成一个单独的类。通常,我们在多个类完成同一件事情,仅仅完成的方式不同时,我们可以考虑使用这种设计模式。

举例:相信,很多人在看到“假如有以下几种价格10,20,50,请你代码实现将他们排序输出”这种题目的时候,很快就写出了以下代码,写之前还不忘了问一下,“对时间复杂度有什么要求吗???需要处理的数据规模大概是多少???”,这时候,别人通常都会面带微笑,说,“对时间复杂度没有要求,数据规模你假设是XX就行了”之类的话。。。

很快的,类似于下面的代码就出来了

/*
 * price.cpp
 *
 *  Created on: 2014年5月11日
 *      Author: pc
 */

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int n;
int price[100];

/**
 * 处理输入逻辑
 */
void hanldeInput() {
	int i;
	for (i = 0; i < n; ++i) {
		scanf("%d", &price[i]);
	}
}

/**
 *相比这里很多朋友会绞尽脑汁的想各种各样的排序算法..
 *其实最后写出来的话,大部分用到的算法还是: 冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序、堆排序
 */
void sort(int price[]) {
	for(int i = n ; i > 0 ; --i){
		for(int j = 0 ; j < i-1 ; ++j){
			if(price[j] > price[j+1]){
				swap(price[j],price[j+1]);
			}
		}
	}
}

/**
 * 处理输出逻辑
 */
void myprint(int price[]) {
	//TODO 此处将他们输出
	for(int i = 0 ; i < n ; ++i){
		printf("%d ",price[i]);
	}

}

int main() {
	while (scanf("%d", &n) != EOF) {
		hanldeInput();
		sort(price);
		myprint(price);
	}
}

尽管有的朋友甚至可能还会把上面的输入逻辑、排序逻辑、输出逻辑都写到main方法里面,但是,大部分都会在写完以后在心里骂一句,“靠,老子是XX区的ACM的XX牌的获得者,居然拿这种题来敷衍我。。”靠。。。这是,只见别人还是一如既往的面带微笑。。。。然后就自我感觉非常良好地离开了。。。。

其实,现在再回首这种题目的时候,再看看若干年前自己写成那样的代码,简直不忍直视。。。

以下谈谈自己遇到类似的问题时,自己的一些思考。

个人觉得,这种题目可能更多关注的不是你的代码实现,而是你在写代码时的架构。

以下是自己的一些思考

1)根据OOP“一切皆对象”的原则,price应该设计成一个类,而不是仅仅是一个int[]。

2)上面的排序逻辑只能作用于Int[],要是某一天用户有一堆double[]类型的数据需要按同样的逻辑进行排序呢???

那你难道ctrl+c\ctrl+v一遍,然后把参数改成double[]类型的??现在的sort方法职能作用领域Price类型的数据,

要是某一天需要对Human类型的数据进行排序呢????难道又重写一遍逻辑类似的sort方法而仅仅是因为参数的

类型不一样???

3)上面的排序逻辑已经写死了,就是用的冒泡排序。要是某一天用户高兴,说我就是喜欢用希尔排序。那你是不是又要把那一坨代码改改改。。。这。。。

这时,可能有一些朋友会说,“我才不管,反正他问的是:假如有以下几种价格10,20,50,请你代码实现将他们排序输出,我只要实现这一个逻辑就行了,管他呢”。。是的,其实这种题只是用户的某一种情况的下的需求的简化一下的版本而已。。。例如今天用户就只说,“我有一堆的Price,你帮我排序一下”,明天他可能就会对你说,“我也有一堆的Human,你也帮我排序一下吧”。。。后天有会对你说,“你之前的那个算法我不喜欢,你换一个吧”。。。。这是你会疯掉的。。。。

所以,以下给出我对这一情况下使用策略模式来设计代码的实现

1、MyComparable

public interface MyComparable {

	public int compareTo(Object o);
}

2、MyComparator

public interface MyComparator {

	public int compare(Object o1,Object o2);
}

3、PriceNumComparator

public class PriceNumComparator implements MyComparator {

	@Override
	public int compare(Object o1, Object o2) {
		Price p1 = (Price)o1;
		Price p2 = (Price)o2;

		if(p1.getNum() > p2.getNum()){
			return 1;
		}else if(p1.getNum() < p2.getNum()){
			return -1;
		}
		return 0;
	}

}

4、PriceWeightComparator

public class PriceWeightComparator implements MyComparator {

	@Override
	public int compare(Object o1, Object o2) {
		Price p1 = (Price)o1;
		Price p2 = (Price)o2;

		if(p1.getWeight() > p2.getWeight()){
			return -1;
		}else if(p1.getWeight() < p2.getWeight()){
			return 1;
		}

		return 0;
	}

}

5、Price

public class Price implements MyComparable{

	public int num;
	public int weight;
	public MyComparator comparator  = new PriceWeightComparator();

	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public int getWeight() {
		return weight;
	}
	public void setWeight(int weight) {
		this.weight = weight;
	}

	public Price() {
		// TODO Auto-generated constructor stub
	}
	public Price(int num, int weight) {
		super();
		this.num = num;
		this.weight = weight;
	}

	@Override
	public String toString() {
		return "Price [num=" + num + ", weight=" + weight + "]";
	}

	@Override
	public int compareTo(Object o) {
		return comparator.compare(this, o);
	}

}

6、Sorter

public class Sorter {

	public static void sort(Object[] os){
		int length = os.length;
		for(int i = length ; i > 0 ; --i){
			for(int j = 0 ; j < i-1 ; ++j){
				MyComparable c1 = (MyComparable) os[j];
				MyComparable c2 = (MyComparable) os[j+1];

				if(c1.compareTo(c2) == 1){
					swap(os, j, j+1);
				}
			}
		}
	}

	public static void swap(Object[] os ,int i,int j){
		Object temp = os[i];
		os[i] = os[j];
		os[j] = temp;
	}

	public static void print(Object[] os){
		int length = os.length;

		for(int i = 0 ; i < length ; ++i){
			System.out.print(os[i] + " ");
		}

		System.out.println();
	}
}

7、Main //用来测试

public class Main {

	public static void main(String[] args) {
		Price[] prices = {
			new Price(1, 1),
			new Price(2, 2),
			new Price(3, 3)
		};

		Sorter.sort(prices);
		Sorter.print(prices);
	}
}

写在最后:

设计模式是一种“把简单东西复杂化”的一种东西,其实更准确的来说,它是一种要求你在开始实现某一个具体功能之前就把相应的架构给想好的开发思路。。。。

从“假如有以下几种价格10,20,50,请你代码实现将他们排序输出”看着设计模式中的策略模式

时间: 2024-12-26 06:08:51

从“假如有以下几种价格10,20,50,请你代码实现将他们排序输出”看着设计模式中的策略模式的相关文章

给你六种面额1 5 10 20 50 100元的纸币假设每种币值的数量足够多

编写程序求组成N元的不同组合的个数.输入一个数字N输出一个也是数字,为组成N的组合个数.如输入2,输出1,输入5,输出2 背包问题: 1 function fn (all) { 2 const arr = [1, 5, 10, 20, 50, 100], 3 len = arr.length, 4 res = []; 5 for (let i = 0; i <= len; i++) { 6 res[i] = []; 7 res[i][0] = 1; 8 } 9 for (let j = 1; j

请从L=[1,10,20,50,20,20,1]中找出重复数。

1 L=[1,10,20,50,20,20,1] 2 L1=[] 3 for i in L: 4 if(L.count(i)>1): 5 L1.append(i) 6 L2=[] 7 for i in L1: 8 if i not in L2: 9 L2.append(i) 10 print L2 原文地址:https://www.cnblogs.com/Python-XiaCaiP/p/8521517.html

一道题采用两种设计模式:对比策略模式和模版方法

摘要 <C++ Primer>习题14.38和14.39分别采用策略模式.模版方法解决问题. 问题 <C++ Primer 5th>习题 14.38 : 编写一个类令其检查某个给定的 string 对象的长度是否与一个阀值相等.使用该对象编写程序,统计并报告输入的文件中长度为 1 的单词有多少个.长度为 2 的单词有多少个........长度为 10 的单词有多少个. <C++ Primer 5th>习题 14.39 : 修改上一题的程序令其报告长度在 1 至 9 之间

23种设计模式中的迭代器模式

迭代器模式:提供一种方法顺序访问一个聚合对象中的各个对象. 那么如何提供一个方法顺序呢? public interface Iterator<T>{ public boolean hasNext(); public T next(); } public class XXX{ private List<XXX> list =new ArrayList<>(); public Iterator getIterator (){ return new XXXIterator()

23种设计模式中的原型模式

原型模式:通过复制现有实例来创建新的实例,无须知道相应类的信息. 个人见解:在大量循环时,需要初始化对象,用 原型模式能节省大量的初始化所花费的时间,值得一谈的是浅复制和深复制 浅复制:Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组.容器对象.引用对象等都不会拷贝 代码 在这里我定义了一个学生类Student.java public class Student implements Cloneable { private String name; public Stude

23种设计模式中的访问者模式

访问者模式:对于一组对象,在不改变数据结构的前提下,增加作用于这些结构元素新的功能. 适用于数据结构相对稳定,它把数据结构和作用于其上的操作解耦,使得操作集合可以相对自由地演化. 优点: 符合单一职责原则 扩展性良好 有益于系统的管理和维护 缺点: 增加新的元素类变得很困难 破坏封装性 适用场合: 如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的

23种设计模式中的桥接模式

桥接模式:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变. 个人见解:实际上是为了同时实现两个协议,而让其中一个协议让父类实现而另一个协议自己实现. public interface IA{ public void a(); } public interface IB{ public void b(); } public ABfather implements IA{ @override public void a(){} } public AB extends ABfather i

【23种设计模式】之策略模式——Strategy

Strategy--策略模式 程序员看问题需要有时间轴的概念,静态可能暴露不出问题,要动态的看. 看问题要加上时间轴. 一.定义 定义一系列算法,把它们一个个封装起来,并且使它们互相替换(变化),该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化) 二.假设场景 根据货币类型,计算税 1.传统思路 public class Strategy1 { ? /** * 根据货币类型,计算值 * 变化:当增加日元,泰铢等情况时,只能添加elseif的代码,违背了开闭原则 * @param

Java经典23种设计模式之行为型模式(四)

本文介绍11种行为型设计模式里的策略模式.模板方法.访问者模式. 一.策略模式 定义一系列的算法,把它们每个封装起来,并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化. 1.Strategy定义所有支持的算法的公共接口.Context使用这个接口来调用某ConcreteStrategy定义的算法. public abstract class Strategy {    public abstract void method();} 2.ConcreteStrategy以Strate